SQL Operations Studio Public Preview 1 (0.23) release source code

This commit is contained in:
Karl Burtram
2017-11-09 14:30:27 -08:00
parent b88ecb8d93
commit 3cdac41339
8829 changed files with 759707 additions and 286 deletions

View File

@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { BackupModelTracker } from 'vs/workbench/parts/backup/common/backupModelTracker';
import { BackupRestorer } from 'vs/workbench/parts/backup/common/backupRestorer';
// Register Backup Model Tracker
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(
BackupModelTracker
);
// Register Backup Restorer
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(
BackupRestorer
);

View File

@@ -0,0 +1,99 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import Uri from 'vs/base/common/uri';
import errors = require('vs/base/common/errors');
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ITextFileService, TextFileModelChangeEvent, StateChange } from 'vs/workbench/services/textfile/common/textfiles';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IFilesConfiguration, AutoSaveConfiguration, CONTENT_CHANGE_EVENT_BUFFER_DELAY } from 'vs/platform/files/common/files';
const AUTO_SAVE_AFTER_DELAY_DISABLED_TIME = CONTENT_CHANGE_EVENT_BUFFER_DELAY + 500;
export class BackupModelTracker implements IWorkbenchContribution {
public _serviceBrand: any;
private configuredAutoSaveAfterDelay: boolean;
private toDispose: IDisposable[];
constructor(
@IBackupFileService private backupFileService: IBackupFileService,
@ITextFileService private textFileService: ITextFileService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@IConfigurationService private configurationService: IConfigurationService
) {
this.toDispose = [];
this.registerListeners();
}
private registerListeners() {
if (!this.backupFileService.backupEnabled) {
return;
}
// Listen for text file model changes
this.toDispose.push(this.textFileService.models.onModelContentChanged((e) => this.onTextFileModelChanged(e)));
this.toDispose.push(this.textFileService.models.onModelSaved((e) => this.discardBackup(e.resource)));
this.toDispose.push(this.textFileService.models.onModelDisposed((e) => this.discardBackup(e)));
// Listen for untitled model changes
this.toDispose.push(this.untitledEditorService.onDidChangeContent((e) => this.onUntitledModelChanged(e)));
this.toDispose.push(this.untitledEditorService.onDidDisposeModel((e) => this.discardBackup(e)));
// Listen to config changes
this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(this.configurationService.getConfiguration<IFilesConfiguration>())));
}
private onConfigurationChange(configuration: IFilesConfiguration): void {
if (!configuration || !configuration.files) {
this.configuredAutoSaveAfterDelay = false;
return;
}
this.configuredAutoSaveAfterDelay =
(configuration.files.autoSave === AutoSaveConfiguration.AFTER_DELAY &&
configuration.files.autoSaveDelay <= AUTO_SAVE_AFTER_DELAY_DISABLED_TIME);
}
private onTextFileModelChanged(event: TextFileModelChangeEvent): void {
if (event.kind === StateChange.REVERTED) {
// This must proceed even if auto save after delay is configured in order to clean up
// any backups made before the config change
this.discardBackup(event.resource);
} else if (event.kind === StateChange.CONTENT_CHANGE) {
// Do not backup when auto save after delay is configured
if (!this.configuredAutoSaveAfterDelay) {
const model = this.textFileService.models.get(event.resource);
this.backupFileService.backupResource(model.getResource(), model.getValue(), model.getVersionId()).done(null, errors.onUnexpectedError);
}
}
}
private onUntitledModelChanged(resource: Uri): void {
if (this.untitledEditorService.isDirty(resource)) {
this.untitledEditorService.loadOrCreate({ resource }).then(model => this.backupFileService.backupResource(resource, model.getValue(), model.getVersionId())).done(null, errors.onUnexpectedError);
} else {
this.discardBackup(resource);
}
}
private discardBackup(resource: Uri): void {
this.backupFileService.discardResourceBackup(resource).done(null, errors.onUnexpectedError);
}
public dispose(): void {
this.toDispose = dispose(this.toDispose);
}
public getId(): string {
return 'vs.backup.backupModelTracker';
}
}

View File

@@ -0,0 +1,112 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { IUntitledEditorService, UNTITLED_SCHEMA } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import errors = require('vs/base/common/errors');
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { Position, IResourceInput, IUntitledResourceInput } from 'vs/platform/editor/common/editor';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { Schemas } from 'vs/base/common/network';
export class BackupRestorer implements IWorkbenchContribution {
// {{SQL CARBON EDIT}}
private static readonly SQLQUERY_REGEX = /SQLQuery\d+/;
private static readonly UNTITLED_REGEX = /Untitled-\d+/;
constructor(
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@IPartService private partService: IPartService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IBackupFileService private backupFileService: IBackupFileService,
@ITextFileService private textFileService: ITextFileService,
@IEditorGroupService private groupService: IEditorGroupService
) {
this.restoreBackups();
}
private restoreBackups(): void {
if (this.backupFileService.backupEnabled) {
this.partService.joinCreation().then(() => {
this.doRestoreBackups().done(null, errors.onUnexpectedError);
});
}
}
private doRestoreBackups(): TPromise<URI[]> {
// Find all files and untitled with backups
return this.backupFileService.getWorkspaceFileBackups().then(backups => {
// Resolve backups that are opened in stacks model
return this.doResolveOpenedBackups(backups).then(unresolved => {
// Some failed to restore or were not opened at all so we open and resolve them manually
if (unresolved.length > 0) {
return this.doOpenEditors(unresolved).then(() => this.doResolveOpenedBackups(unresolved));
}
return void 0;
});
});
}
private doResolveOpenedBackups(backups: URI[]): TPromise<URI[]> {
const stacks = this.groupService.getStacksModel();
const restorePromises: TPromise<any>[] = [];
const unresolved: URI[] = [];
backups.forEach(backup => {
if (stacks.isOpen(backup)) {
if (backup.scheme === Schemas.file) {
restorePromises.push(this.textFileService.models.loadOrCreate(backup).then(null, () => unresolved.push(backup)));
} else if (backup.scheme === UNTITLED_SCHEMA) {
restorePromises.push(this.untitledEditorService.loadOrCreate({ resource: backup }).then(null, () => unresolved.push(backup)));
}
} else {
unresolved.push(backup);
}
});
return TPromise.join(restorePromises).then(() => unresolved, () => unresolved);
}
private doOpenEditors(resources: URI[]): TPromise<void> {
const stacks = this.groupService.getStacksModel();
const hasOpenedEditors = stacks.groups.length > 0;
const inputs = resources.map((resource, index) => this.resolveInput(resource, index, hasOpenedEditors));
// Open all remaining backups as editors and resolve them to load their backups
return this.editorService.openEditors(inputs.map(input => { return { input, position: Position.ONE }; })).then(() => void 0);
}
private resolveInput(resource: URI, index: number, hasOpenedEditors: boolean): IResourceInput | IUntitledResourceInput {
const options = { pinned: true, preserveFocus: true, inactive: index > 0 || hasOpenedEditors };
// {{SQL CARBON EDIT}}
if (resource.scheme === UNTITLED_SCHEMA
&& !BackupRestorer.UNTITLED_REGEX.test(resource.fsPath)
&& !BackupRestorer.SQLQUERY_REGEX.test(resource.fsPath)) {
// TODO@Ben debt: instead of guessing if an untitled file has an associated file path or not
// this information should be provided by the backup service and stored as meta data within
return { filePath: resource.fsPath, options };
}
return { resource, options };
}
public getId(): string {
return 'vs.backup.backupRestorer';
}
}

View File

@@ -0,0 +1,159 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import * as path from 'path';
import * as cp from 'child_process';
import * as pfs from 'vs/base/node/pfs';
import { nfcall } from 'vs/base/common/async';
import { TPromise } from 'vs/base/common/winjs.base';
import URI from 'vs/base/common/uri';
import { Action } from 'vs/base/common/actions';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actionRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { IMessageService, Severity } from 'vs/platform/message/common/message';
import { IEditorService } from 'vs/platform/editor/common/editor';
import product from 'vs/platform/node/product';
interface ILegacyUse {
file: string;
lineNumber: number;
}
function ignore<T>(code: string, value: T = null): (err: any) => TPromise<T> {
return err => err.code === code ? TPromise.as<T>(value) : TPromise.wrapError<T>(err);
}
const root = URI.parse(require.toUrl('')).fsPath;
const source = path.resolve(root, '..', 'bin', 'code');
function isAvailable(): TPromise<boolean> {
return pfs.exists(source);
}
class InstallAction extends Action {
static ID = 'workbench.action.installCommandLine';
static LABEL = nls.localize('install', "Install '{0}' command in PATH", product.applicationName);
constructor(
id: string,
label: string,
@IMessageService private messageService: IMessageService,
@IEditorService private editorService: IEditorService
) {
super(id, label);
}
private get target(): string {
return `/usr/local/bin/${product.applicationName}`;
}
run(): TPromise<void> {
return isAvailable().then(isAvailable => {
if (!isAvailable) {
const message = nls.localize('not available', "This command is not available");
this.messageService.show(Severity.Info, message);
return undefined;
}
return this.isInstalled()
.then(isInstalled => {
if (!isAvailable || isInstalled) {
return TPromise.as(null);
} else {
const createSymlink = () => {
return pfs.unlink(this.target)
.then(null, ignore('ENOENT'))
.then(() => pfs.symlink(source, this.target));
};
return createSymlink().then(null, err => {
if (err.code === 'EACCES' || err.code === 'ENOENT') {
return this.createBinFolder()
.then(() => createSymlink());
}
return TPromise.wrapError(err);
});
}
})
.then(() => {
this.messageService.show(Severity.Info, nls.localize('successIn', "Shell command '{0}' successfully installed in PATH.", product.applicationName));
});
});
}
private isInstalled(): TPromise<boolean> {
return pfs.lstat(this.target)
.then(stat => stat.isSymbolicLink())
.then(() => pfs.readlink(this.target))
.then(link => link === source)
.then(null, ignore('ENOENT', false));
}
private createBinFolder(): TPromise<void> {
return new TPromise<void>((c, e) => {
const message = nls.localize('warnEscalation', "Code will now prompt with 'osascript' for Administrator privileges to install the shell command.");
const actions = [
new Action('ok', nls.localize('ok', "OK"), '', true, () => {
const command = 'osascript -e "do shell script \\"mkdir -p /usr/local/bin && chown \\" & (do shell script (\\"whoami\\")) & \\" /usr/local/bin\\" with administrator privileges"';
nfcall(cp.exec, command, {})
.then(null, _ => TPromise.wrapError(new Error(nls.localize('cantCreateBinFolder', "Unable to create '/usr/local/bin'."))))
.done(c, e);
return null;
}),
new Action('cancel2', nls.localize('cancel2', "Cancel"), '', true, () => { e(new Error(nls.localize('aborted', "Aborted"))); return null; })
];
this.messageService.show(Severity.Info, { message, actions });
});
}
}
class UninstallAction extends Action {
static ID = 'workbench.action.uninstallCommandLine';
static LABEL = nls.localize('uninstall', "Uninstall '{0}' command from PATH", product.applicationName);
constructor(
id: string,
label: string,
@IMessageService private messageService: IMessageService
) {
super(id, label);
}
private get target(): string {
return `/usr/local/bin/${product.applicationName}`;
}
run(): TPromise<void> {
return isAvailable().then(isAvailable => {
if (!isAvailable) {
const message = nls.localize('not available', "This command is not available");
this.messageService.show(Severity.Info, message);
return undefined;
}
return pfs.unlink(this.target)
.then(null, ignore('ENOENT'))
.then(() => {
this.messageService.show(Severity.Info, nls.localize('successFrom', "Shell command '{0}' successfully uninstalled from PATH.", product.applicationName));
});
});
}
}
if (process.platform === 'darwin') {
const category = nls.localize('shellCommand', "Shell Command");
const workbenchActionsRegistry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(InstallAction, InstallAction.ID, InstallAction.LABEL), 'Shell Command: Install \'code\' command in PATH', category);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(UninstallAction, UninstallAction.ID, UninstallAction.LABEL), 'Shell Command: Uninstall \'code\' command from PATH', category);
}

View File

@@ -0,0 +1,16 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './electron-browser/accessibility';
import './electron-browser/inspectKeybindings';
import './electron-browser/menuPreventer';
import './electron-browser/selectionClipboard';
import './electron-browser/textMate/inspectTMScopes';
import './electron-browser/toggleMinimap';
import './electron-browser/toggleMultiCursorModifier';
import './electron-browser/toggleRenderControlCharacter';
import './electron-browser/toggleRenderWhitespace';
import './electron-browser/toggleWordWrap';
import './electron-browser/wordWrapMigration';

View File

@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-editor .accessibilityHelpWidget {
padding: 10px;
vertical-align: middle;
}

View File

@@ -0,0 +1,337 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./accessibility';
import * as nls from 'vs/nls';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Disposable } from 'vs/base/common/lifecycle';
import * as strings from 'vs/base/common/strings';
import * as dom from 'vs/base/browser/dom';
import { renderFormattedText } from 'vs/base/browser/htmlContentRenderer';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { Widget } from 'vs/base/browser/ui/widget';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICommonCodeEditor, IEditorContribution } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { editorAction, CommonEditorRegistry, EditorAction, EditorCommand } from 'vs/editor/common/editorCommonExtensions';
import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition } from 'vs/editor/browser/editorBrowser';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { ToggleTabFocusModeAction } from 'vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { editorWidgetBackground, widgetShadow, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import * as platform from 'vs/base/common/platform';
import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import URI from 'vs/base/common/uri';
const CONTEXT_ACCESSIBILITY_WIDGET_VISIBLE = new RawContextKey<boolean>('accessibilityHelpWidgetVisible', false);
@editorContribution
class AccessibilityHelpController extends Disposable implements IEditorContribution {
private static ID = 'editor.contrib.accessibilityHelpController';
public static get(editor: ICommonCodeEditor): AccessibilityHelpController {
return editor.getContribution<AccessibilityHelpController>(AccessibilityHelpController.ID);
}
private _editor: ICodeEditor;
private _widget: AccessibilityHelpWidget;
constructor(
editor: ICodeEditor,
@IInstantiationService instantiationService: IInstantiationService
) {
super();
this._editor = editor;
this._widget = this._register(instantiationService.createInstance(AccessibilityHelpWidget, this._editor));
}
public getId(): string {
return AccessibilityHelpController.ID;
}
public show(): void {
this._widget.show();
}
public hide(): void {
this._widget.hide();
}
}
class AccessibilityHelpWidget extends Widget implements IOverlayWidget {
private static ID = 'editor.contrib.accessibilityHelpWidget';
private static WIDTH = 500;
private static HEIGHT = 300;
private _editor: ICodeEditor;
private _domNode: FastDomNode<HTMLElement>;
private _contentDomNode: FastDomNode<HTMLElement>;
private _isVisible: boolean;
private _isVisibleKey: IContextKey<boolean>;
constructor(
editor: ICodeEditor,
@IContextKeyService private _contextKeyService: IContextKeyService,
@IKeybindingService private _keybindingService: IKeybindingService,
@IConfigurationService private _configurationService: IConfigurationService,
@IConfigurationEditingService private _configurationEditingService: IConfigurationEditingService,
@IOpenerService private _openerService: IOpenerService
) {
super();
this._editor = editor;
this._isVisibleKey = CONTEXT_ACCESSIBILITY_WIDGET_VISIBLE.bindTo(this._contextKeyService);
this._domNode = createFastDomNode(document.createElement('div'));
this._domNode.setClassName('accessibilityHelpWidget');
this._domNode.setWidth(AccessibilityHelpWidget.WIDTH);
this._domNode.setHeight(AccessibilityHelpWidget.HEIGHT);
this._domNode.setDisplay('none');
this._domNode.setAttribute('role', 'dialog');
this._domNode.setAttribute('aria-hidden', 'true');
this._contentDomNode = createFastDomNode(document.createElement('div'));
this._contentDomNode.setAttribute('role', 'document');
this._domNode.appendChild(this._contentDomNode);
this._isVisible = false;
this._register(this._editor.onDidLayoutChange(() => {
if (this._isVisible) {
this._layout();
}
}));
// Intentionally not configurable!
this._register(dom.addStandardDisposableListener(this._contentDomNode.domNode, 'keydown', (e) => {
if (!this._isVisible) {
return;
}
if (e.equals(KeyMod.CtrlCmd | KeyCode.KEY_E)) {
alert(nls.localize('emergencyConfOn', "Now changing the setting `editor.accessibilitySupport` to 'on'."));
this._configurationEditingService.writeConfiguration(ConfigurationTarget.USER, {
key: 'editor.accessibilitySupport',
value: 'on'
});
e.preventDefault();
e.stopPropagation();
}
if (e.equals(KeyMod.CtrlCmd | KeyCode.KEY_H)) {
alert(nls.localize('openingDocs', "Now opening the VS Code Accessibility documentation page."));
this._openerService.open(URI.parse('https://go.microsoft.com/fwlink/?linkid=851010'));
e.preventDefault();
e.stopPropagation();
}
}));
this.onblur(this._contentDomNode.domNode, () => {
this.hide();
});
this._editor.addOverlayWidget(this);
}
public dispose(): void {
this._editor.removeOverlayWidget(this);
super.dispose();
}
public getId(): string {
return AccessibilityHelpWidget.ID;
}
public getDomNode(): HTMLElement {
return this._domNode.domNode;
}
public getPosition(): IOverlayWidgetPosition {
return {
preference: null
};
}
public show(): void {
if (this._isVisible) {
return;
}
this._isVisible = true;
this._isVisibleKey.set(true);
this._layout();
this._domNode.setDisplay('block');
this._domNode.setAttribute('aria-hidden', 'false');
this._contentDomNode.domNode.tabIndex = 0;
this._buildContent();
this._contentDomNode.domNode.focus();
}
private _descriptionForCommand(commandId: string, msg: string, noKbMsg: string): string {
let kb = this._keybindingService.lookupKeybinding(commandId);
if (kb) {
return strings.format(msg, kb.getAriaLabel());
}
return strings.format(noKbMsg, commandId);
}
private _buildContent() {
let opts = this._editor.getConfiguration();
let text = nls.localize('introMsg', "Thank you for trying out VS Code's accessibility options.");
text += '\n\n' + nls.localize('status', "Status:");
const configuredValue = this._configurationService.getConfiguration<editorOptions.IEditorOptions>('editor').accessibilitySupport;
const actualValue = opts.accessibilitySupport;
const emergencyTurnOnMessage = (
platform.isMacintosh
? nls.localize('changeConfigToOnMac', "To configure the editor to be permanently optimized for usage with a Screen Reader press Command+E now.")
: nls.localize('changeConfigToOnWinLinux', "To configure the editor to be permanently optimized for usage with a Screen Reader press Control+E now.")
);
switch (configuredValue) {
case 'auto':
switch (actualValue) {
case platform.AccessibilitySupport.Unknown:
// Should never happen in VS Code
text += '\n\n - ' + nls.localize('auto_unknown', "The editor is configured to use platform APIs to detect when a Screen Reader is attached, but the current runtime does not support this.");
break;
case platform.AccessibilitySupport.Enabled:
text += '\n\n - ' + nls.localize('auto_on', "The editor has automatically detected a Screen Reader is attached.");
break;
case platform.AccessibilitySupport.Disabled:
text += '\n\n - ' + nls.localize('auto_off', "The editor is configured to automatically detect when a Screen Reader is attached, which is not the case at this time.");
text += ' ' + emergencyTurnOnMessage;
break;
}
break;
case 'on':
text += '\n\n - ' + nls.localize('configuredOn', "The editor is configured to be permanently optimized for usage with a Screen Reader - you can change this by editing the setting `editor.accessibilitySupport`.");
break;
case 'off':
text += '\n\n - ' + nls.localize('configuredOff', "The editor is configured to never be optimized for usage with a Screen Reader.");
text += ' ' + emergencyTurnOnMessage;
break;
}
const NLS_TAB_FOCUS_MODE_ON = nls.localize('tabFocusModeOnMsg', "Pressing Tab in the current editor will move focus to the next focusable element. Toggle this behavior by pressing {0}.");
const NLS_TAB_FOCUS_MODE_ON_NO_KB = nls.localize('tabFocusModeOnMsgNoKb', "Pressing Tab in the current editor will move focus to the next focusable element. The command {0} is currently not triggerable by a keybinding.");
const NLS_TAB_FOCUS_MODE_OFF = nls.localize('tabFocusModeOffMsg', "Pressing Tab in the current editor will insert the tab character. Toggle this behavior by pressing {0}.");
const NLS_TAB_FOCUS_MODE_OFF_NO_KB = nls.localize('tabFocusModeOffMsgNoKb', "Pressing Tab in the current editor will insert the tab character. The command {0} is currently not triggerable by a keybinding.");
if (opts.tabFocusMode) {
text += '\n\n - ' + this._descriptionForCommand(ToggleTabFocusModeAction.ID, NLS_TAB_FOCUS_MODE_ON, NLS_TAB_FOCUS_MODE_ON_NO_KB);
} else {
text += '\n\n - ' + this._descriptionForCommand(ToggleTabFocusModeAction.ID, NLS_TAB_FOCUS_MODE_OFF, NLS_TAB_FOCUS_MODE_OFF_NO_KB);
}
const openDocMessage = (
platform.isMacintosh
? nls.localize('openDocMac', "Press Command+H now to open a browser window with more VS Code information related to Accessibility.")
: nls.localize('openDocWinLinux', "Press Control+H now to open a browser window with more VS Code information related to Accessibility.")
);
text += '\n\n' + openDocMessage;
text += '\n\n' + nls.localize('outroMsg', "You can dismiss this tooltip and return to the editor by pressing Escape or Shift+Escape.");
this._contentDomNode.domNode.appendChild(renderFormattedText(text));
// Per https://www.w3.org/TR/wai-aria/roles#document, Authors SHOULD provide a title or label for documents
this._contentDomNode.domNode.setAttribute('aria-label', text);
}
public hide(): void {
if (!this._isVisible) {
return;
}
this._isVisible = false;
this._isVisibleKey.reset();
this._domNode.setDisplay('none');
this._domNode.setAttribute('aria-hidden', 'true');
this._contentDomNode.domNode.tabIndex = -1;
dom.clearNode(this._contentDomNode.domNode);
this._editor.focus();
}
private _layout(): void {
let editorLayout = this._editor.getLayoutInfo();
let top = Math.round((editorLayout.height - AccessibilityHelpWidget.HEIGHT) / 2);
this._domNode.setTop(top);
let left = Math.round((editorLayout.width - AccessibilityHelpWidget.WIDTH) / 2);
this._domNode.setLeft(left);
}
}
@editorAction
class ShowAccessibilityHelpAction extends EditorAction {
constructor() {
super({
id: 'editor.action.showAccessibilityHelp',
label: nls.localize('ShowAccessibilityHelpAction', "Show Accessibility Help"),
alias: 'Show Accessibility Help',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.Alt | KeyCode.F1
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
let controller = AccessibilityHelpController.get(editor);
if (controller) {
controller.show();
}
}
}
const AccessibilityHelpCommand = EditorCommand.bindToContribution<AccessibilityHelpController>(AccessibilityHelpController.get);
CommonEditorRegistry.registerEditorCommand(new AccessibilityHelpCommand({
id: 'closeAccessibilityHelp',
precondition: CONTEXT_ACCESSIBILITY_WIDGET_VISIBLE,
handler: x => x.hide(),
kbOpts: {
weight: CommonEditorRegistry.commandWeight(100),
kbExpr: EditorContextKeys.focus,
primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape]
}
}));
registerThemingParticipant((theme, collector) => {
let widgetBackground = theme.getColor(editorWidgetBackground);
if (widgetBackground) {
collector.addRule(`.monaco-editor .accessibilityHelpWidget { background-color: ${widgetBackground}; }`);
}
let widgetShadowColor = theme.getColor(widgetShadow);
if (widgetShadowColor) {
collector.addRule(`.monaco-editor .accessibilityHelpWidget { box-shadow: 0 2px 8px ${widgetShadowColor}; }`);
}
let hcBorder = theme.getColor(contrastBorder);
if (hcBorder) {
collector.addRule(`.monaco-editor .accessibilityHelpWidget { border: 2px solid ${hcBorder}; }`);
}
});

View File

@@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vs/nls';
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { WorkbenchKeybindingService } from 'vs/workbench/services/keybinding/electron-browser/keybindingService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IUntitledResourceInput } from 'vs/platform/editor/common/editor';
@editorAction
class InspectKeyMap extends EditorAction {
constructor() {
super({
id: 'workbench.action.inspectKeyMappings',
label: nls.localize('workbench.action.inspectKeyMap', "Developer: Inspect Key Mappings"),
alias: 'Developer: Inspect Key Mappings',
precondition: null
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
const keybindingService = accessor.get(IKeybindingService);
const editorService = accessor.get(IWorkbenchEditorService);
if (keybindingService instanceof WorkbenchKeybindingService) {
editorService.openEditor({ contents: keybindingService.dumpDebugInfo(), options: { pinned: true } } as IUntitledResourceInput);
}
}
}

View File

@@ -0,0 +1,384 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vs/nls';
import { parse, ParseError } from 'vs/base/common/json';
import { readFile } from 'vs/base/node/pfs';
import { CharacterPair, LanguageConfiguration, IAutoClosingPair, IAutoClosingPairConditional, IndentationRule, CommentRule } from 'vs/editor/common/modes/languageConfiguration';
import { IModeService } from 'vs/editor/common/services/modeService';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { Extensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { LanguageIdentifier } from 'vs/editor/common/modes';
import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService';
interface IRegExp {
pattern: string;
flags?: string;
}
interface IIndentationRules {
decreaseIndentPattern: string | IRegExp;
increaseIndentPattern: string | IRegExp;
indentNextLinePattern?: string | IRegExp;
unIndentedLinePattern?: string | IRegExp;
}
interface ILanguageConfiguration {
comments?: CommentRule;
brackets?: CharacterPair[];
autoClosingPairs?: (CharacterPair | IAutoClosingPairConditional)[];
surroundingPairs?: (CharacterPair | IAutoClosingPair)[];
wordPattern?: string | IRegExp;
indentationRules?: IIndentationRules;
}
export class LanguageConfigurationFileHandler {
private _modeService: IModeService;
private _done: boolean[];
constructor(
@ITextMateService textMateService: ITextMateService,
@IModeService modeService: IModeService
) {
this._modeService = modeService;
this._done = [];
// Listen for hints that a language configuration is needed/usefull and then load it once
this._modeService.onDidCreateMode((mode) => this._loadConfigurationsForMode(mode.getLanguageIdentifier()));
textMateService.onDidEncounterLanguage((languageId) => {
this._loadConfigurationsForMode(this._modeService.getLanguageIdentifier(languageId));
});
}
private _loadConfigurationsForMode(languageIdentifier: LanguageIdentifier): void {
if (this._done[languageIdentifier.id]) {
return;
}
this._done[languageIdentifier.id] = true;
let configurationFiles = this._modeService.getConfigurationFiles(languageIdentifier.language);
configurationFiles.forEach((configFilePath) => this._handleConfigFile(languageIdentifier, configFilePath));
}
private _handleConfigFile(languageIdentifier: LanguageIdentifier, configFilePath: string): void {
readFile(configFilePath).then((fileContents) => {
const errors: ParseError[] = [];
const configuration = <ILanguageConfiguration>parse(fileContents.toString(), errors);
if (errors.length) {
console.error(nls.localize('parseErrors', "Errors parsing {0}: {1}", configFilePath, errors.join('\n')));
}
this._handleConfig(languageIdentifier, configuration);
}, (err) => {
console.error(err);
});
}
private _handleConfig(languageIdentifier: LanguageIdentifier, configuration: ILanguageConfiguration): void {
let richEditConfig: LanguageConfiguration = {};
if (configuration.comments) {
richEditConfig.comments = configuration.comments;
}
if (configuration.brackets) {
richEditConfig.brackets = configuration.brackets;
}
if (configuration.autoClosingPairs) {
richEditConfig.autoClosingPairs = this._mapCharacterPairs(configuration.autoClosingPairs);
}
if (configuration.surroundingPairs) {
richEditConfig.surroundingPairs = this._mapCharacterPairs(configuration.surroundingPairs);
}
if (configuration.wordPattern) {
try {
let wordPattern = this._parseRegex(configuration.wordPattern);
if (wordPattern) {
richEditConfig.wordPattern = wordPattern;
}
} catch (error) {
// Malformed regexes are ignored
}
}
if (configuration.indentationRules) {
let indentationRules = this._mapIndentationRules(configuration.indentationRules);
if (indentationRules) {
richEditConfig.indentationRules = indentationRules;
}
}
LanguageConfigurationRegistry.register(languageIdentifier, richEditConfig);
}
private _parseRegex(value: string | IRegExp) {
if (typeof value === 'string') {
return new RegExp(value, '');
} else if (typeof value === 'object') {
return new RegExp(value.pattern, value.flags);
}
return null;
}
private _mapIndentationRules(indentationRules: IIndentationRules): IndentationRule {
try {
let increaseIndentPattern = this._parseRegex(indentationRules.increaseIndentPattern);
let decreaseIndentPattern = this._parseRegex(indentationRules.decreaseIndentPattern);
if (increaseIndentPattern && decreaseIndentPattern) {
let result: IndentationRule = {
increaseIndentPattern: increaseIndentPattern,
decreaseIndentPattern: decreaseIndentPattern
};
if (indentationRules.indentNextLinePattern) {
result.indentNextLinePattern = this._parseRegex(indentationRules.indentNextLinePattern);
}
if (indentationRules.unIndentedLinePattern) {
result.unIndentedLinePattern = this._parseRegex(indentationRules.unIndentedLinePattern);
}
return result;
}
} catch (error) {
// Malformed regexes are ignored
}
return null;
}
private _mapCharacterPairs(pairs: (CharacterPair | IAutoClosingPairConditional)[]): IAutoClosingPairConditional[] {
return pairs.map(pair => {
if (Array.isArray(pair)) {
return { open: pair[0], close: pair[1] };
}
return <IAutoClosingPairConditional>pair;
});
}
}
const schemaId = 'vscode://schemas/language-configuration';
const schema: IJSONSchema = {
default: {
comments: {
blockComment: ['/*', '*/'],
lineComment: '//'
},
brackets: [['(', ')'], ['[', ']'], ['{', '}']],
autoClosingPairs: [['(', ')'], ['[', ']'], ['{', '}']],
surroundingPairs: [['(', ')'], ['[', ']'], ['{', '}']]
},
definitions: {
openBracket: {
type: 'string',
description: nls.localize('schema.openBracket', 'The opening bracket character or string sequence.')
},
closeBracket: {
type: 'string',
description: nls.localize('schema.closeBracket', 'The closing bracket character or string sequence.')
},
bracketPair: {
type: 'array',
items: [{
$ref: '#definitions/openBracket'
}, {
$ref: '#definitions/closeBracket'
}]
}
},
properties: {
comments: {
default: {
blockComment: ['/*', '*/'],
lineComment: '//'
},
description: nls.localize('schema.comments', 'Defines the comment symbols'),
type: 'object',
properties: {
blockComment: {
type: 'array',
description: nls.localize('schema.blockComments', 'Defines how block comments are marked.'),
items: [{
type: 'string',
description: nls.localize('schema.blockComment.begin', 'The character sequence that starts a block comment.')
}, {
type: 'string',
description: nls.localize('schema.blockComment.end', 'The character sequence that ends a block comment.')
}]
},
lineComment: {
type: 'string',
description: nls.localize('schema.lineComment', 'The character sequence that starts a line comment.')
}
}
},
brackets: {
default: [['(', ')'], ['[', ']'], ['{', '}']],
description: nls.localize('schema.brackets', 'Defines the bracket symbols that increase or decrease the indentation.'),
type: 'array',
items: {
$ref: '#definitions/bracketPair'
}
},
autoClosingPairs: {
default: [['(', ')'], ['[', ']'], ['{', '}']],
description: nls.localize('schema.autoClosingPairs', 'Defines the bracket pairs. When a opening bracket is entered, the closing bracket is inserted automatically.'),
type: 'array',
items: {
oneOf: [{
$ref: '#definitions/bracketPair'
}, {
type: 'object',
properties: {
open: {
$ref: '#definitions/openBracket'
},
close: {
$ref: '#definitions/closeBracket'
},
notIn: {
type: 'array',
description: nls.localize('schema.autoClosingPairs.notIn', 'Defines a list of scopes where the auto pairs are disabled.'),
items: {
enum: ['string', 'comment']
}
}
}
}]
}
},
surroundingPairs: {
default: [['(', ')'], ['[', ']'], ['{', '}']],
description: nls.localize('schema.surroundingPairs', 'Defines the bracket pairs that can be used to surround a selected string.'),
type: 'array',
items: {
oneOf: [{
$ref: '#definitions/bracketPair'
}, {
type: 'object',
properties: {
open: {
$ref: '#definitions/openBracket'
},
close: {
$ref: '#definitions/closeBracket'
}
}
}]
}
},
wordPattern: {
default: '',
description: nls.localize('schema.wordPattern', 'The word definition for the language.'),
type: ['string', 'object'],
properties: {
pattern: {
type: 'string',
description: nls.localize('schema.wordPattern.pattern', 'The RegExp pattern used to match words.'),
default: '',
},
flags: {
type: 'string',
description: nls.localize('schema.wordPattern.flags', 'The RegExp flags used to match words.'),
default: 'g',
pattern: '^([gimuy]+)$',
patternErrorMessage: nls.localize('schema.wordPattern.flags.errorMessage', 'Must match the pattern `/^([gimuy]+)$/`.')
}
}
},
indentationRules: {
default: {
increaseIndentPattern: '',
decreaseIndentPattern: ''
},
description: nls.localize('schema.indentationRules', 'The language\'s indentation settings.'),
type: 'object',
properties: {
increaseIndentPattern: {
type: ['string', 'object'],
description: nls.localize('schema.indentationRules.increaseIndentPattern', 'If a line matches this pattern, then all the lines after it should be indented once (until another rule matches).'),
properties: {
pattern: {
type: 'string',
description: nls.localize('schema.indentationRules.increaseIndentPattern.pattern', 'The RegExp pattern for increaseIndentPattern.'),
default: '',
},
flags: {
type: 'string',
description: nls.localize('schema.indentationRules.increaseIndentPattern.flags', 'The RegExp flags for increaseIndentPattern.'),
default: '',
pattern: '^([gimuy]+)$',
patternErrorMessage: nls.localize('schema.indentationRules.increaseIndentPattern.errorMessage', 'Must match the pattern `/^([gimuy]+)$/`.')
}
}
},
decreaseIndentPattern: {
type: ['string', 'object'],
description: nls.localize('schema.indentationRules.decreaseIndentPattern', 'If a line matches this pattern, then all the lines after it should be unindendented once (until another rule matches).'),
properties: {
pattern: {
type: 'string',
description: nls.localize('schema.indentationRules.decreaseIndentPattern.pattern', 'The RegExp pattern for decreaseIndentPattern.'),
default: '',
},
flags: {
type: 'string',
description: nls.localize('schema.indentationRules.decreaseIndentPattern.flags', 'The RegExp flags for decreaseIndentPattern.'),
default: '',
pattern: '^([gimuy]+)$',
patternErrorMessage: nls.localize('schema.indentationRules.decreaseIndentPattern.errorMessage', 'Must match the pattern `/^([gimuy]+)$/`.')
}
}
},
indentNextLinePattern: {
type: ['string', 'object'],
description: nls.localize('schema.indentationRules.indentNextLinePattern', 'If a line matches this pattern, then **only the next line** after it should be indented once.'),
properties: {
pattern: {
type: 'string',
description: nls.localize('schema.indentationRules.indentNextLinePattern.pattern', 'The RegExp pattern for indentNextLinePattern.'),
default: '',
},
flags: {
type: 'string',
description: nls.localize('schema.indentationRules.indentNextLinePattern.flags', 'The RegExp flags for indentNextLinePattern.'),
default: '',
pattern: '^([gimuy]+)$',
patternErrorMessage: nls.localize('schema.indentationRules.indentNextLinePattern.errorMessage', 'Must match the pattern `/^([gimuy]+)$/`.')
}
}
},
unIndentedLinePattern: {
type: ['string', 'object'],
description: nls.localize('schema.indentationRules.unIndentedLinePattern', 'If a line matches this pattern, then its indentation should not be changed and it should not be evaluated against the other rules.'),
properties: {
pattern: {
type: 'string',
description: nls.localize('schema.indentationRules.unIndentedLinePattern.pattern', 'The RegExp pattern for unIndentedLinePattern.'),
default: '',
},
flags: {
type: 'string',
description: nls.localize('schema.indentationRules.unIndentedLinePattern.flags', 'The RegExp flags for unIndentedLinePattern.'),
default: '',
pattern: '^([gimuy]+)$',
patternErrorMessage: nls.localize('schema.indentationRules.unIndentedLinePattern.errorMessage', 'Must match the pattern `/^([gimuy]+)$/`.')
}
}
}
}
}
}
};
let schemaRegistry = <IJSONContributionRegistry>Registry.as(Extensions.JSONContribution);
schemaRegistry.registerSchema(schemaId, schema);

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.st0{opacity:0}.st0,.st1{fill:#f6f6f6}.st2{fill:#424242}</style><g id="outline"><path class="st0" d="M0 0h16v16H0z"/><path class="st1" d="M16 3H9v.445c-.034-.07-.062-.145-.1-.21a2.318 2.318 0 0 0-.759-.793C7.81 2.229 7 2.117 7 2.109V0H4v2.438c-.078-.042-.15-.092-.233-.125a2.685 2.685 0 0 0-1.013-.188c-.184 0-.392.016-.619.055a5.422 5.422 0 0 0-.506.115c-.149.045-.337.096-.493.162-.173.077-.39.151-.533.25L0 3.006v3.17c0 .297.045.56.136.821.1.291.255.525.454.736.207.224.462.351.75.467.065.027.137.026.205.039a2.827 2.827 0 0 0-.651.532 3.064 3.064 0 0 0-.6 1.061 3.81 3.81 0 0 0-.188 1.21c0 .402.062.784.185 1.137.132.377.323.709.562.978a2.748 2.748 0 0 0 2.131.942c.333 0 .595-.042.876-.13a2.61 2.61 0 0 0 .678-.333L5 13.225v-1.811L8.586 15h4.828l-2-2H16V3zM5 10.586V8.523l-.556-.404c-.081-.043-.152-.083-.228-.119h1.96c.196 0 .409.266.634.266.187 0 .366-.007.538-.029L5 10.586z"/></g><g id="icon_x5F_bg"><path class="st2" d="M10 4v2h3v4H9l2-2H9l-3 3 3 3h2l-2-2h6V4zM3.869 3.568a1.21 1.21 0 0 0-.473-.329c-.274-.111-.623-.15-1.055-.076a3.5 3.5 0 0 0-.711.208 1.501 1.501 0 0 0-.234.125l-.043.03v1.056l.168-.139c.149-.124.326-.225.527-.303.196-.074.399-.113.604-.113.188 0 .33.051.431.157.087.095.137.248.147.456l-.962.144c-.219.03-.41.086-.57.166a1.245 1.245 0 0 0-.398.311 1.234 1.234 0 0 0-.229.426 1.714 1.714 0 0 0 .011 1.008 1.096 1.096 0 0 0 .638.67c.155.063.328.093.528.093a1.25 1.25 0 0 0 .978-.441v.345h1.007V4.769c0-.255-.03-.484-.089-.681a1.423 1.423 0 0 0-.275-.52zm-.636 1.896V5.7c0 .119-.018.231-.055.341a.745.745 0 0 1-.377.447.694.694 0 0 1-.512.027.454.454 0 0 1-.156-.094.389.389 0 0 1-.094-.139.474.474 0 0 1-.035-.186c0-.077.009-.147.024-.212a.33.33 0 0 1 .078-.141.436.436 0 0 1 .161-.109 1.3 1.3 0 0 1 .305-.073l.661-.097zM8.284 4.397a2.253 2.253 0 0 0-.244-.656 1.354 1.354 0 0 0-.436-.459 1.165 1.165 0 0 0-.642-.173 1.136 1.136 0 0 0-.69.223 1.312 1.312 0 0 0-.264.266V1.119H5.09v6.224h.918v-.281a1.023 1.023 0 0 0 .472.328c.098.032.208.047.33.047.255 0 .483-.06.677-.177.192-.115.355-.278.486-.486a2.29 2.29 0 0 0 .293-.718 3.87 3.87 0 0 0 .096-.886 3.76 3.76 0 0 0-.078-.773zm-.861.758c0 .232-.02.439-.059.613-.036.172-.09.315-.159.424a.639.639 0 0 1-.233.237.582.582 0 0 1-.565.014.683.683 0 0 1-.211-.183.925.925 0 0 1-.141-.283 1.187 1.187 0 0 1-.054-.358v-.517c0-.164.02-.314.059-.447.037-.132.088-.242.157-.336a.668.668 0 0 1 .228-.208.584.584 0 0 1 .289-.071.554.554 0 0 1 .497.279c.063.099.108.214.143.354.031.143.049.306.049.482zM2.409 10.019a.913.913 0 0 1 .316-.239c.218-.1.547-.105.766-.018.104.042.204.1.32.184l.329.26V9.064l-.096-.062a1.932 1.932 0 0 0-.905-.215c-.308 0-.593.057-.846.168-.25.11-.467.27-.647.475a2.072 2.072 0 0 0-.403.717c-.09.272-.137.57-.137.895 0 .289.043.561.129.808.087.249.212.471.374.652.161.185.361.333.597.441.232.104.493.155.778.155.233 0 .434-.028.613-.084a1.85 1.85 0 0 0 .466-.217l.078-.061v-.889l-.2.095a.402.402 0 0 1-.076.026c-.05.017-.099.035-.128.049-.036.023-.227.09-.227.09-.06.024-.14.043-.218.059a.977.977 0 0 1-.599-.057.827.827 0 0 1-.306-.225 1.088 1.088 0 0 1-.205-.376 1.728 1.728 0 0 1-.076-.529c0-.21.028-.399.083-.56.054-.158.129-.294.22-.4z"/></g></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,8 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.toggle-word-wrap-action {
background: url('WordWrap_16x.svg') center center no-repeat;
}

View File

@@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { KeyMod } from 'vs/base/common/keyCodes';
import { Disposable } from 'vs/base/common/lifecycle';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
/**
* Prevents the top-level menu from showing up when doing Alt + Click in the editor
*/
@editorContribution
export class MenuPreventer extends Disposable implements IEditorContribution {
private static ID = 'editor.contrib.menuPreventer';
private _editor: ICodeEditor;
private _altListeningMouse: boolean;
private _altMouseTriggered: boolean;
constructor(editor: ICodeEditor) {
super();
this._editor = editor;
this._altListeningMouse = false;
this._altMouseTriggered = false;
// A global crossover handler to prevent menu bar from showing up
// When <alt> is hold, we will listen to mouse events and prevent
// the release event up <alt> if the mouse is triggered.
this._register(this._editor.onMouseDown((e) => {
if (this._altListeningMouse) {
this._altMouseTriggered = true;
}
}));
this._register(this._editor.onKeyDown((e) => {
if (e.equals(KeyMod.Alt)) {
if (!this._altListeningMouse) {
this._altMouseTriggered = false;
}
this._altListeningMouse = true;
}
}));
this._register(this._editor.onKeyUp((e) => {
if (e.equals(KeyMod.Alt)) {
if (this._altMouseTriggered) {
e.preventDefault();
}
this._altListeningMouse = false;
this._altMouseTriggered = false;
}
}));
}
public getId(): string {
return MenuPreventer.ID;
}
}

View File

@@ -0,0 +1,103 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { clipboard } from 'electron';
import * as platform from 'vs/base/common/platform';
import { ICodeEditor, IEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
import { Disposable } from 'vs/base/common/lifecycle';
import { EndOfLinePreference, IEditorContribution } from 'vs/editor/common/editorCommon';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { RunOnceScheduler } from 'vs/base/common/async';
import { Range } from 'vs/editor/common/core/range';
import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
import { ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
@editorContribution
export class SelectionClipboard extends Disposable implements IEditorContribution {
private static ID = 'editor.contrib.selectionClipboard';
constructor(editor: ICodeEditor, @IContextKeyService contextKeyService: IContextKeyService) {
super();
if (platform.isLinux) {
let isEnabled = editor.getConfiguration().contribInfo.selectionClipboard;
this._register(editor.onDidChangeConfiguration((e: IConfigurationChangedEvent) => {
if (e.contribInfo) {
isEnabled = editor.getConfiguration().contribInfo.selectionClipboard;
}
}));
this._register(editor.onMouseDown((e: IEditorMouseEvent) => {
if (!isEnabled) {
return;
}
if (!editor.getModel()) {
return;
}
if (e.event.middleButton) {
e.event.preventDefault();
editor.focus();
if (e.target.position) {
editor.setPosition(e.target.position);
}
process.nextTick(() => {
// TODO@Alex: electron weirdness: calling clipboard.readText('selection') generates a paste event, so no need to execute paste ourselves
clipboard.readText('selection');
// keybindingService.executeCommand(Handler.Paste, {
// text: clipboard.readText('selection'),
// pasteOnNewLine: false
// });
});
}
}));
let setSelectionToClipboard = this._register(new RunOnceScheduler(() => {
let model = editor.getModel();
if (!model) {
return;
}
let selections = editor.getSelections();
selections = selections.slice(0);
selections.sort(Range.compareRangesUsingStarts);
let result: string[] = [];
for (let i = 0; i < selections.length; i++) {
let sel = selections[i];
if (sel.isEmpty()) {
// Only write if all cursors have selection
return;
}
result.push(model.getValueInRange(sel, EndOfLinePreference.TextDefined));
}
let textToCopy = result.join(model.getEOL());
clipboard.writeText(textToCopy, 'selection');
}, 100));
this._register(editor.onDidChangeCursorSelection((e: ICursorSelectionChangedEvent) => {
if (!isEnabled) {
return;
}
setSelectionToClipboard.schedule();
}));
}
}
public getId(): string {
return SelectionClipboard.ID;
}
public dispose(): void {
super.dispose();
}
}

View File

@@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.tm-inspect-widget {
z-index: 50;
-webkit-user-select: text;
-ms-user-select: text;
-khtml-user-select: text;
-moz-user-select: text;
-o-user-select: text;
user-select: text;
padding: 10px;
}
.tm-token {
font-family: monospace;
}
.tm-metadata-separator {
height: 1px;
border: 0;
}
.tm-token-length {
font-weight: normal;
font-size: 60%;
float: right;
}
.tm-metadata-table {
width: 100%;
}
.tm-metadata-value {
font-family: monospace;
text-align: right;
}
.tm-theme-selector {
font-family: monospace;
}

View File

@@ -0,0 +1,390 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./inspectTMScopes';
import * as nls from 'vs/nls';
import * as dom from 'vs/base/browser/dom';
import { Disposable } from 'vs/base/common/lifecycle';
import { escape } from 'vs/base/common/strings';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Position } from 'vs/editor/common/core/position';
import { ICommonCodeEditor, IEditorContribution, IModel } from 'vs/editor/common/editorCommon';
import { editorAction, EditorAction, ServicesAccessor } from 'vs/editor/common/editorCommonExtensions';
import { ICodeEditor, ContentWidgetPositionPreference, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { TPromise } from 'vs/base/common/winjs.base';
import { IGrammar, StackElement, IToken } from 'vscode-textmate';
import { ITextMateService } from 'vs/workbench/services/textMate/electron-browser/textMateService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { TokenMetadata } from 'vs/editor/common/model/tokensBinaryEncoding';
import { TokenizationRegistry, LanguageIdentifier, FontStyle, StandardTokenType } from 'vs/editor/common/modes';
import { CharCode } from 'vs/base/common/charCode';
import { findMatchingThemeRule } from 'vs/workbench/services/textMate/electron-browser/TMHelper';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { Color } from 'vs/base/common/color';
import { IMessageService } from 'vs/platform/message/common/message';
import Severity from 'vs/base/common/severity';
import { registerThemingParticipant, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
import { editorHoverBackground, editorHoverBorder } from 'vs/platform/theme/common/colorRegistry';
@editorContribution
class InspectTMScopesController extends Disposable implements IEditorContribution {
private static ID = 'editor.contrib.inspectTMScopes';
public static get(editor: ICommonCodeEditor): InspectTMScopesController {
return editor.getContribution<InspectTMScopesController>(InspectTMScopesController.ID);
}
private _editor: ICodeEditor;
private _textMateService: ITextMateService;
private _themeService: IWorkbenchThemeService;
private _modeService: IModeService;
private _messageService: IMessageService;
private _widget: InspectTMScopesWidget;
constructor(
editor: ICodeEditor,
@ITextMateService textMateService: ITextMateService,
@IModeService modeService: IModeService,
@IWorkbenchThemeService themeService: IWorkbenchThemeService,
@IMessageService messageService: IMessageService,
) {
super();
this._editor = editor;
this._textMateService = textMateService;
this._themeService = themeService;
this._modeService = modeService;
this._messageService = messageService;
this._widget = null;
this._register(this._editor.onDidChangeModel((e) => this.stop()));
this._register(this._editor.onDidChangeModelLanguage((e) => this.stop()));
this._register(this._editor.onKeyUp((e) => e.keyCode === KeyCode.Escape && this.stop()));
}
public getId(): string {
return InspectTMScopesController.ID;
}
public dispose(): void {
this.stop();
super.dispose();
}
public launch(): void {
if (this._widget) {
return;
}
if (!this._editor.getModel()) {
return;
}
this._widget = new InspectTMScopesWidget(this._editor, this._textMateService, this._modeService, this._themeService, this._messageService);
}
public stop(): void {
if (this._widget) {
this._widget.dispose();
this._widget = null;
}
}
public toggle(): void {
if (!this._widget) {
this.launch();
} else {
this.stop();
}
}
}
@editorAction
class InspectTMScopes extends EditorAction {
constructor() {
super({
id: 'editor.action.inspectTMScopes',
label: nls.localize('inspectTMScopes', "Developer: Inspect TM Scopes"),
alias: 'Developer: Inspect TM Scopes',
precondition: null
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
let controller = InspectTMScopesController.get(editor);
if (controller) {
controller.toggle();
}
}
}
interface ICompleteLineTokenization {
startState: StackElement;
tokens1: IToken[];
tokens2: Uint32Array;
endState: StackElement;
}
interface IDecodedMetadata {
languageIdentifier: LanguageIdentifier;
tokenType: StandardTokenType;
fontStyle: FontStyle;
foreground: Color;
background: Color;
}
function renderTokenText(tokenText: string): string {
if (tokenText.length > 40) {
tokenText = tokenText.substr(0, 20) + '…' + tokenText.substr(tokenText.length - 20);
}
let result: string = '';
for (let charIndex = 0, len = tokenText.length; charIndex < len; charIndex++) {
let charCode = tokenText.charCodeAt(charIndex);
switch (charCode) {
case CharCode.Tab:
result += '&rarr;';
break;
case CharCode.Space:
result += '&middot;';
break;
case CharCode.LessThan:
result += '&lt;';
break;
case CharCode.GreaterThan:
result += '&gt;';
break;
case CharCode.Ampersand:
result += '&amp;';
break;
default:
result += String.fromCharCode(charCode);
}
}
return result;
}
class InspectTMScopesWidget extends Disposable implements IContentWidget {
private static _ID = 'editor.contrib.inspectTMScopesWidget';
// Editor.IContentWidget.allowEditorOverflow
public readonly allowEditorOverflow = true;
private _isDisposed: boolean;
private readonly _editor: ICodeEditor;
private readonly _modeService: IModeService;
private readonly _themeService: IWorkbenchThemeService;
private readonly _messageService: IMessageService;
private readonly _model: IModel;
private readonly _domNode: HTMLElement;
private readonly _grammar: TPromise<IGrammar>;
constructor(
editor: ICodeEditor,
textMateService: ITextMateService,
modeService: IModeService,
themeService: IWorkbenchThemeService,
messageService: IMessageService
) {
super();
this._isDisposed = false;
this._editor = editor;
this._modeService = modeService;
this._themeService = themeService;
this._messageService = messageService;
this._model = this._editor.getModel();
this._domNode = document.createElement('div');
this._domNode.className = 'tm-inspect-widget';
this._grammar = textMateService.createGrammar(this._model.getLanguageIdentifier().language);
this._beginCompute(this._editor.getPosition());
this._register(this._editor.onDidChangeCursorPosition((e) => this._beginCompute(this._editor.getPosition())));
this._editor.addContentWidget(this);
}
public dispose(): void {
this._isDisposed = true;
this._editor.removeContentWidget(this);
super.dispose();
}
public getId(): string {
return InspectTMScopesWidget._ID;
}
private _beginCompute(position: Position): void {
dom.clearNode(this._domNode);
this._domNode.appendChild(document.createTextNode(nls.localize('inspectTMScopesWidget.loading', "Loading...")));
this._grammar.then(
(grammar) => this._compute(grammar, position),
(err) => {
this._messageService.show(Severity.Warning, err);
setTimeout(() => {
InspectTMScopesController.get(this._editor).stop();
});
}
);
}
private _compute(grammar: IGrammar, position: Position): void {
if (this._isDisposed) {
return;
}
let data = this._getTokensAtLine(grammar, position.lineNumber);
let token1Index = 0;
for (let i = data.tokens1.length - 1; i >= 0; i--) {
let t = data.tokens1[i];
if (position.column - 1 >= t.startIndex) {
token1Index = i;
break;
}
}
let token2Index = 0;
for (let i = (data.tokens2.length >>> 1); i >= 0; i--) {
if (position.column - 1 >= data.tokens2[(i << 1)]) {
token2Index = i;
break;
}
}
let result = '';
let tokenStartIndex = data.tokens1[token1Index].startIndex;
let tokenEndIndex = data.tokens1[token1Index].endIndex;
let tokenText = this._model.getLineContent(position.lineNumber).substring(tokenStartIndex, tokenEndIndex);
result += `<h2 class="tm-token">${renderTokenText(tokenText)}<span class="tm-token-length">(${tokenText.length} ${tokenText.length === 1 ? 'char' : 'chars'})</span></h2>`;
result += `<hr class="tm-metadata-separator" style="clear:both"/>`;
let metadata = this._decodeMetadata(data.tokens2[(token2Index << 1) + 1]);
result += `<table class="tm-metadata-table"><tbody>`;
result += `<tr><td class="tm-metadata-key">language</td><td class="tm-metadata-value">${escape(metadata.languageIdentifier.language)}</td>`;
result += `<tr><td class="tm-metadata-key">token type</td><td class="tm-metadata-value">${this._tokenTypeToString(metadata.tokenType)}</td>`;
result += `<tr><td class="tm-metadata-key">font style</td><td class="tm-metadata-value">${this._fontStyleToString(metadata.fontStyle)}</td>`;
result += `<tr><td class="tm-metadata-key">foreground</td><td class="tm-metadata-value">${Color.Format.CSS.formatHexA(metadata.foreground)}</td>`;
result += `<tr><td class="tm-metadata-key">background</td><td class="tm-metadata-value">${Color.Format.CSS.formatHexA(metadata.background)}</td>`;
result += `</tbody></table>`;
let theme = this._themeService.getColorTheme();
result += `<hr class="tm-metadata-separator"/>`;
let matchingRule = findMatchingThemeRule(theme, data.tokens1[token1Index].scopes);
if (matchingRule) {
result += `<code class="tm-theme-selector">${matchingRule.rawSelector}\n${JSON.stringify(matchingRule.settings, null, '\t')}</code>`;
} else {
result += `<span class="tm-theme-selector">No theme selector.</span>`;
}
result += `<hr class="tm-metadata-separator"/>`;
result += `<ul>`;
for (let i = data.tokens1[token1Index].scopes.length - 1; i >= 0; i--) {
result += `<li>${escape(data.tokens1[token1Index].scopes[i])}</li>`;
}
result += `</ul>`;
this._domNode.innerHTML = result;
this._editor.layoutContentWidget(this);
}
private _decodeMetadata(metadata: number): IDecodedMetadata {
let colorMap = TokenizationRegistry.getColorMap();
let languageId = TokenMetadata.getLanguageId(metadata);
let tokenType = TokenMetadata.getTokenType(metadata);
let fontStyle = TokenMetadata.getFontStyle(metadata);
let foreground = TokenMetadata.getForeground(metadata);
let background = TokenMetadata.getBackground(metadata);
return {
languageIdentifier: this._modeService.getLanguageIdentifier(languageId),
tokenType: tokenType,
fontStyle: fontStyle,
foreground: colorMap[foreground],
background: colorMap[background]
};
}
private _tokenTypeToString(tokenType: StandardTokenType): string {
switch (tokenType) {
case StandardTokenType.Other: return 'Other';
case StandardTokenType.Comment: return 'Comment';
case StandardTokenType.String: return 'String';
case StandardTokenType.RegEx: return 'RegEx';
}
return '??';
}
private _fontStyleToString(fontStyle: FontStyle): string {
let r = '';
if (fontStyle & FontStyle.Italic) {
r += 'italic ';
}
if (fontStyle & FontStyle.Bold) {
r += 'bold ';
}
if (fontStyle & FontStyle.Underline) {
r += 'underline ';
}
if (r.length === 0) {
r = '---';
}
return r;
}
private _getTokensAtLine(grammar: IGrammar, lineNumber: number): ICompleteLineTokenization {
let stateBeforeLine = this._getStateBeforeLine(grammar, lineNumber);
let tokenizationResult1 = grammar.tokenizeLine(this._model.getLineContent(lineNumber), stateBeforeLine);
let tokenizationResult2 = grammar.tokenizeLine2(this._model.getLineContent(lineNumber), stateBeforeLine);
return {
startState: stateBeforeLine,
tokens1: tokenizationResult1.tokens,
tokens2: tokenizationResult2.tokens,
endState: tokenizationResult1.ruleStack
};
}
private _getStateBeforeLine(grammar: IGrammar, lineNumber: number): StackElement {
let state: StackElement = null;
for (let i = 1; i < lineNumber; i++) {
let tokenizationResult = grammar.tokenizeLine(this._model.getLineContent(i), state);
state = tokenizationResult.ruleStack;
}
return state;
}
public getDomNode(): HTMLElement {
return this._domNode;
}
public getPosition(): IContentWidgetPosition {
return {
position: this._editor.getPosition(),
preference: [ContentWidgetPositionPreference.BELOW, ContentWidgetPositionPreference.ABOVE]
};
}
}
registerThemingParticipant((theme, collector) => {
let border = theme.getColor(editorHoverBorder);
if (border) {
let borderWidth = theme.type === HIGH_CONTRAST ? 2 : 1;
collector.addRule(`.monaco-editor .tm-inspect-widget { border: ${borderWidth}px solid ${border}; }`);
collector.addRule(`.monaco-editor .tm-inspect-widget .tm-metadata-separator { background-color: ${border}; }`);
}
let background = theme.getColor(editorHoverBackground);
if (background) {
collector.addRule(`.monaco-editor .tm-inspect-widget { background-color: ${background}; }`);
}
});

View File

@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vs/nls';
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions';
import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
@editorAction
export class ToggleMinimapAction extends EditorAction {
constructor() {
super({
id: 'editor.action.toggleMinimap',
label: nls.localize('toggleMinimap', "View: Toggle Minimap"),
alias: 'View: Toggle Minimap',
precondition: null
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
const configurationEditingService = accessor.get(IConfigurationEditingService);
const newValue = !editor.getConfiguration().viewInfo.minimap.enabled;
configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'editor.minimap.enabled', value: newValue });
}
}

View File

@@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import * as nls from 'vs/nls';
import { Registry } from 'vs/platform/registry/common/platform';
import { Action } from 'vs/base/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actionRegistry';
import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
export class ToggleMultiCursorModifierAction extends Action {
public static ID = 'workbench.action.toggleMultiCursorModifier';
public static LABEL = nls.localize('toggleLocation', "Toggle Multi-Cursor Modifier");
private static multiCursorModifierConfigurationKey = 'editor.multiCursorModifier';
constructor(
id: string,
label: string,
@IConfigurationService private configurationService: IConfigurationService,
@IConfigurationEditingService private configurationEditingService: IConfigurationEditingService
) {
super(id, label);
this.enabled = !!this.configurationService && !!this.configurationEditingService;
}
public run(): TPromise<any> {
const editorConf = this.configurationService.getConfiguration<{ multiCursorModifier: 'ctrlCmd' | 'alt' }>('editor');
const newValue: 'ctrlCmd' | 'alt' = (editorConf.multiCursorModifier === 'ctrlCmd' ? 'alt' : 'ctrlCmd');
this.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: ToggleMultiCursorModifierAction.multiCursorModifierConfigurationKey, value: newValue });
return TPromise.as(null);
}
}
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMultiCursorModifierAction, ToggleMultiCursorModifierAction.ID, ToggleMultiCursorModifierAction.LABEL), 'Toggle Multi-Cursor Modifier');

View File

@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vs/nls';
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions';
import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
@editorAction
export class ToggleRenderControlCharacterAction extends EditorAction {
constructor() {
super({
id: 'editor.action.toggleRenderControlCharacter',
label: nls.localize('toggleRenderControlCharacters', "View: Toggle Control Characters"),
alias: 'View: Toggle Control Characters',
precondition: null
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
const configurationEditingService = accessor.get(IConfigurationEditingService);
let newRenderControlCharacters = !editor.getConfiguration().viewInfo.renderControlCharacters;
configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'editor.renderControlCharacters', value: newRenderControlCharacters });
}
}

View File

@@ -0,0 +1,37 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vs/nls';
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { editorAction, ServicesAccessor, EditorAction } from 'vs/editor/common/editorCommonExtensions';
import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
@editorAction
export class ToggleRenderWhitespaceAction extends EditorAction {
constructor() {
super({
id: 'editor.action.toggleRenderWhitespace',
label: nls.localize('toggleRenderWhitespace', "View: Toggle Render Whitespace"),
alias: 'View: Toggle Render Whitespace',
precondition: null
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
const configurationEditingService = accessor.get(IConfigurationEditingService);
let renderWhitespace = editor.getConfiguration().viewInfo.renderWhitespace;
let newRenderWhitespace: string;
if (renderWhitespace === 'none') {
newRenderWhitespace = 'all';
} else {
newRenderWhitespace = 'none';
}
configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'editor.renderWhitespace', value: newRenderWhitespace });
}
}

View File

@@ -0,0 +1,280 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/codeEditor';
import * as nls from 'vs/nls';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ICommonCodeEditor, IEditorContribution, IModel } from 'vs/editor/common/editorCommon';
import { editorAction, ServicesAccessor, EditorAction, commonEditorContribution } from 'vs/editor/common/editorCommonExtensions';
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Disposable } from 'vs/base/common/lifecycle';
import { IMessageService } from 'vs/platform/message/common/message';
import Severity from 'vs/base/common/severity';
import URI from 'vs/base/common/uri';
import { InternalEditorOptions, EDITOR_DEFAULTS } from 'vs/editor/common/config/editorOptions';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
const transientWordWrapState = 'transientWordWrapState';
const isWordWrapMinifiedKey = 'isWordWrapMinified';
const isDominatedByLongLinesKey = 'isDominatedByLongLines';
const inDiffEditorKey = 'inDiffEditor';
/**
* State written/read by the toggle word wrap action and associated with a particular model.
*/
interface IWordWrapTransientState {
readonly forceWordWrap: 'on' | 'off' | 'wordWrapColumn' | 'bounded';
readonly forceWordWrapMinified: boolean;
}
interface IWordWrapState {
readonly configuredWordWrap: 'on' | 'off' | 'wordWrapColumn' | 'bounded';
readonly configuredWordWrapMinified: boolean;
readonly transientState: IWordWrapTransientState;
}
/**
* Store (in memory) the word wrap state for a particular model.
*/
function writeTransientState(model: IModel, state: IWordWrapTransientState, codeEditorService: ICodeEditorService): void {
codeEditorService.setTransientModelProperty(model, transientWordWrapState, state);
}
/**
* Read (in memory) the word wrap state for a particular model.
*/
function readTransientState(model: IModel, codeEditorService: ICodeEditorService): IWordWrapTransientState {
return codeEditorService.getTransientModelProperty(model, transientWordWrapState);
}
function readWordWrapState(model: IModel, configurationService: ITextResourceConfigurationService, codeEditorService: ICodeEditorService): IWordWrapState {
const editorConfig = configurationService.getConfiguration(model.uri, 'editor') as { wordWrap: 'on' | 'off' | 'wordWrapColumn' | 'bounded'; wordWrapMinified: boolean };
let _configuredWordWrap = editorConfig && (typeof editorConfig.wordWrap === 'string' || typeof editorConfig.wordWrap === 'boolean') ? editorConfig.wordWrap : void 0;
// Compatibility with old true or false values
if (<any>_configuredWordWrap === true) {
_configuredWordWrap = 'on';
} else if (<any>_configuredWordWrap === false) {
_configuredWordWrap = 'off';
}
const _configuredWordWrapMinified = editorConfig && typeof editorConfig.wordWrapMinified === 'boolean' ? editorConfig.wordWrapMinified : void 0;
const _transientState = readTransientState(model, codeEditorService);
return {
configuredWordWrap: _configuredWordWrap,
configuredWordWrapMinified: (typeof _configuredWordWrapMinified === 'boolean' ? _configuredWordWrapMinified : EDITOR_DEFAULTS.wordWrapMinified),
transientState: _transientState
};
}
function toggleWordWrap(editor: ICommonCodeEditor, state: IWordWrapState): IWordWrapState {
if (state.transientState) {
// toggle off => go to null
return {
configuredWordWrap: state.configuredWordWrap,
configuredWordWrapMinified: state.configuredWordWrapMinified,
transientState: null
};
}
const config = editor.getConfiguration();
let transientState: IWordWrapTransientState;
const actualWrappingInfo = config.wrappingInfo;
if (actualWrappingInfo.isWordWrapMinified) {
// => wrapping due to minified file
transientState = {
forceWordWrap: 'off',
forceWordWrapMinified: false
};
} else if (state.configuredWordWrap !== 'off') {
// => wrapping is configured to be on (or some variant)
transientState = {
forceWordWrap: 'off',
forceWordWrapMinified: false
};
} else {
// => wrapping is configured to be off
transientState = {
forceWordWrap: 'on',
forceWordWrapMinified: state.configuredWordWrapMinified
};
}
return {
configuredWordWrap: state.configuredWordWrap,
configuredWordWrapMinified: state.configuredWordWrapMinified,
transientState: transientState
};
}
function applyWordWrapState(editor: ICommonCodeEditor, state: IWordWrapState): void {
if (state.transientState) {
// toggle is on
editor.updateOptions({
wordWrap: state.transientState.forceWordWrap,
wordWrapMinified: state.transientState.forceWordWrapMinified
});
return;
}
// toggle is off
editor.updateOptions({
wordWrap: state.configuredWordWrap,
wordWrapMinified: state.configuredWordWrapMinified
});
}
@editorAction
class ToggleWordWrapAction extends EditorAction {
constructor() {
super({
id: 'editor.action.toggleWordWrap',
label: nls.localize('toggle.wordwrap', "View: Toggle Word Wrap"),
alias: 'View: Toggle Word Wrap',
precondition: null,
kbOpts: {
kbExpr: null,
primary: KeyMod.Alt | KeyCode.KEY_Z
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
const editorConfiguration = editor.getConfiguration();
if (editorConfiguration.wrappingInfo.inDiffEditor) {
// Cannot change wrapping settings inside the diff editor
const messageService = accessor.get(IMessageService);
messageService.show(Severity.Info, nls.localize('wordWrap.notInDiffEditor', "Cannot toggle word wrap in a diff editor."));
return;
}
const textResourceConfigurationService = accessor.get(ITextResourceConfigurationService);
const codeEditorService = accessor.get(ICodeEditorService);
const model = editor.getModel();
if (!canToggleWordWrap(model.uri)) {
return;
}
// Read the current state
const currentState = readWordWrapState(model, textResourceConfigurationService, codeEditorService);
// Compute the new state
const newState = toggleWordWrap(editor, currentState);
// Write the new state
writeTransientState(model, newState.transientState, codeEditorService);
// Apply the new state
applyWordWrapState(editor, newState);
}
}
@commonEditorContribution
class ToggleWordWrapController extends Disposable implements IEditorContribution {
private static _ID = 'editor.contrib.toggleWordWrapController';
constructor(
private readonly editor: ICommonCodeEditor,
@IContextKeyService readonly contextKeyService: IContextKeyService,
@ITextResourceConfigurationService readonly configurationService: ITextResourceConfigurationService,
@ICodeEditorService readonly codeEditorService: ICodeEditorService
) {
super();
const configuration = this.editor.getConfiguration();
const isWordWrapMinified = this.contextKeyService.createKey(isWordWrapMinifiedKey, this._isWordWrapMinified(configuration));
const isDominatedByLongLines = this.contextKeyService.createKey(isDominatedByLongLinesKey, this._isDominatedByLongLines(configuration));
const inDiffEditor = this.contextKeyService.createKey(inDiffEditorKey, this._inDiffEditor(configuration));
this._register(editor.onDidChangeConfiguration((e) => {
if (!e.wrappingInfo) {
return;
}
const configuration = this.editor.getConfiguration();
isWordWrapMinified.set(this._isWordWrapMinified(configuration));
isDominatedByLongLines.set(this._isDominatedByLongLines(configuration));
inDiffEditor.set(this._inDiffEditor(configuration));
}));
this._register(editor.onDidChangeModel((e) => {
// Ensure correct word wrap settings
const newModel = this.editor.getModel();
if (!newModel) {
return;
}
const configuration = this.editor.getConfiguration();
if (this._inDiffEditor(configuration)) {
return;
}
if (!canToggleWordWrap(newModel.uri)) {
return;
}
// Read current configured values and toggle state
const desiredState = readWordWrapState(newModel, this.configurationService, this.codeEditorService);
// Apply the state
applyWordWrapState(editor, desiredState);
}));
}
private _isWordWrapMinified(config: InternalEditorOptions): boolean {
return config.wrappingInfo.isWordWrapMinified;
}
private _isDominatedByLongLines(config: InternalEditorOptions): boolean {
return config.wrappingInfo.isDominatedByLongLines;
}
private _inDiffEditor(config: InternalEditorOptions): boolean {
return config.wrappingInfo.inDiffEditor;
}
public getId(): string {
return ToggleWordWrapController._ID;
}
}
function canToggleWordWrap(uri: URI): boolean {
if (!uri) {
return false;
}
return (uri.scheme !== 'output' && uri.scheme !== 'vscode');
}
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: 'editor.action.toggleWordWrap',
title: nls.localize('unwrapMinified', "Disable wrapping for this file"),
iconClass: 'toggle-word-wrap-action'
},
group: 'navigation',
order: 1,
when: ContextKeyExpr.and(
ContextKeyExpr.not(inDiffEditorKey),
ContextKeyExpr.has(isDominatedByLongLinesKey),
ContextKeyExpr.has(isWordWrapMinifiedKey)
)
});
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
id: 'editor.action.toggleWordWrap',
title: nls.localize('wrapMinified', "Enable wrapping for this file"),
iconClass: 'toggle-word-wrap-action'
},
group: 'navigation',
order: 1,
when: ContextKeyExpr.and(
ContextKeyExpr.not(inDiffEditorKey),
ContextKeyExpr.has(isDominatedByLongLinesKey),
ContextKeyExpr.not(isWordWrapMinifiedKey)
)
});

View File

@@ -0,0 +1,142 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vs/nls';
import { Disposable } from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IMessageService } from 'vs/platform/message/common/message';
import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences';
import { Action } from 'vs/base/common/actions';
import Severity from 'vs/base/common/severity';
interface IStorageData {
dontShowPrompt: boolean;
}
class WordWrapMigrationStorage {
private static KEY = 'wordWrapMigration';
private _storageService: IStorageService;
private _value: IStorageData;
constructor(storageService: IStorageService) {
this._storageService = storageService;
this._value = this._read();
}
private _read(): IStorageData {
let jsonValue = this._storageService.get(WordWrapMigrationStorage.KEY, StorageScope.GLOBAL);
if (!jsonValue) {
return null;
}
try {
return JSON.parse(jsonValue);
} catch (err) {
return null;
}
}
public get(): IStorageData {
return this._value;
}
public set(data: IStorageData): void {
this._value = data;
this._storageService.store(WordWrapMigrationStorage.KEY, JSON.stringify(this._value), StorageScope.GLOBAL);
}
}
@editorContribution
class WordWrapMigrationController extends Disposable implements IEditorContribution {
private static ID = 'editor.contrib.wordWrapMigrationController';
private static _checked = false;
constructor(
editor: ICodeEditor,
@IConfigurationService private configurationService: IConfigurationService,
@IMessageService private messageService: IMessageService,
@IStorageService private storageService: IStorageService,
@IPreferencesService private preferencesService: IPreferencesService
) {
super();
this._promptIfNecessary();
}
public getId(): string {
return WordWrapMigrationController.ID;
}
private _promptIfNecessary(): void {
if (WordWrapMigrationController._checked) {
// Already checked
return;
}
WordWrapMigrationController._checked = true;
let result = this.configurationService.lookup('editor.wrappingColumn');
if (typeof result.value === 'undefined') {
// Setting is not used
return;
}
const storage = new WordWrapMigrationStorage(this.storageService);
const storedData = storage.get();
if (storedData && storedData.dontShowPrompt) {
// Do not prompt stored
return;
}
let isUserSetting = (typeof result.user !== 'undefined');
this._prompt(storage, isUserSetting);
}
private _prompt(storage: WordWrapMigrationStorage, userSettings: boolean): void {
const okAction = new Action(
'wordWrapMigration.ok',
nls.localize('wordWrapMigration.ok', "OK"),
null,
true,
() => TPromise.as(true)
);
const dontShowAgainAction = new Action(
'wordWrapMigration.dontShowAgain',
nls.localize('wordWrapMigration.dontShowAgain', "Don't show again"),
null,
true,
() => {
storage.set({
dontShowPrompt: true
});
return TPromise.as(true);
}
);
const openSettings = new Action(
'wordWrapMigration.openSettings',
nls.localize('wordWrapMigration.openSettings', "Open Settings"),
null,
true,
() => {
if (userSettings) {
this.preferencesService.openGlobalSettings();
} else {
this.preferencesService.openWorkspaceSettings();
}
return TPromise.as(true);
}
);
this.messageService.show(Severity.Info, {
message: nls.localize('wordWrapMigration.prompt', "The setting `editor.wrappingColumn` has been deprecated in favor of `editor.wordWrap`."),
actions: [okAction, openSettings, dontShowAgainAction]
});
}
}

View File

@@ -0,0 +1,158 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!../browser/media/breakpointWidget';
import * as nls from 'vs/nls';
import * as errors from 'vs/base/common/errors';
import { KeyCode } from 'vs/base/common/keyCodes';
import { isWindows, isMacintosh } from 'vs/base/common/platform';
import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import * as lifecycle from 'vs/base/common/lifecycle';
import * as dom from 'vs/base/browser/dom';
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/browser/zoneWidget';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IDebugService, IBreakpoint, IRawBreakpoint } from 'vs/workbench/parts/debug/common/debug';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { once } from 'vs/base/common/functional';
import { attachInputBoxStyler, attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService';
const $ = dom.$;
const EXPRESSION_PLACEHOLDER = nls.localize('breakpointWidgetExpressionPlaceholder', "Break when expression evaluates to true. 'Enter' to accept, 'esc' to cancel.");
const EXPRESSION_ARIA_LABEL = nls.localize('breakpointWidgetAriaLabel', "The program will only stop here if this condition is true. Press Enter to accept or Escape to cancel.");
const HIT_COUNT_PLACEHOLDER = nls.localize('breakpointWidgetHitCountPlaceholder', "Break when hit count condition is met. 'Enter' to accept, 'esc' to cancel.");
const HIT_COUNT_ARIA_LABEL = nls.localize('breakpointWidgetHitCountAriaLabel', "The program will only stop here if the hit count is met. Press Enter to accept or Escape to cancel.");
export class BreakpointWidget extends ZoneWidget {
private inputBox: InputBox;
private toDispose: lifecycle.IDisposable[];
private hitCountContext: boolean;
private hitCountInput: string;
private conditionInput: string;
constructor(editor: ICodeEditor, private lineNumber: number, private column: number,
@IContextViewService private contextViewService: IContextViewService,
@IDebugService private debugService: IDebugService,
@IThemeService private themeService: IThemeService
) {
super(editor, { showFrame: true, showArrow: false, frameWidth: 1 });
this.toDispose = [];
this.hitCountInput = '';
this.conditionInput = '';
this.create();
}
private get placeholder(): string {
return this.hitCountContext ? HIT_COUNT_PLACEHOLDER : EXPRESSION_PLACEHOLDER;
}
private get ariaLabel(): string {
return this.hitCountContext ? HIT_COUNT_ARIA_LABEL : EXPRESSION_ARIA_LABEL;
}
private getInputBoxValue(breakpoint: IBreakpoint): string {
if (this.hitCountContext) {
return breakpoint && breakpoint.hitCondition ? breakpoint.hitCondition : this.hitCountInput;
}
return breakpoint && breakpoint.condition ? breakpoint.condition : this.conditionInput;
}
protected _fillContainer(container: HTMLElement): void {
this.setCssClass('breakpoint-widget');
const uri = this.editor.getModel().uri;
const breakpoint = this.debugService.getModel().getBreakpoints().filter(bp => bp.lineNumber === this.lineNumber && bp.column === this.column && bp.uri.toString() === uri.toString()).pop();
this.hitCountContext = breakpoint && breakpoint.hitCondition && !breakpoint.condition;
const selected = this.hitCountContext ? 1 : 0;
const selectBox = new SelectBox([nls.localize('expression', "Expression"), nls.localize('hitCount', "Hit Count")], selected);
this.toDispose.push(attachSelectBoxStyler(selectBox, this.themeService));
selectBox.render(dom.append(container, $('.breakpoint-select-container')));
selectBox.onDidSelect(e => {
this.hitCountContext = e.selected === 'Hit Count';
if (this.hitCountContext) {
this.conditionInput = this.inputBox.value;
} else {
this.hitCountInput = this.inputBox.value;
}
this.inputBox.setAriaLabel(this.ariaLabel);
this.inputBox.setPlaceHolder(this.placeholder);
this.inputBox.value = this.getInputBoxValue(breakpoint);
});
const inputBoxContainer = dom.append(container, $('.inputBoxContainer'));
this.inputBox = new InputBox(inputBoxContainer, this.contextViewService, {
placeholder: this.placeholder,
ariaLabel: this.ariaLabel
});
this.toDispose.push(attachInputBoxStyler(this.inputBox, this.themeService));
this.toDispose.push(this.inputBox);
dom.addClass(this.inputBox.inputElement, isWindows ? 'windows' : isMacintosh ? 'mac' : 'linux');
this.inputBox.value = this.getInputBoxValue(breakpoint);
// Due to an electron bug we have to do the timeout, otherwise we do not get focus
setTimeout(() => this.inputBox.focus(), 0);
let disposed = false;
const wrapUp = once((success: boolean) => {
if (!disposed) {
disposed = true;
if (success) {
// if there is already a breakpoint on this location - remove it.
const oldBreakpoint = this.debugService.getModel().getBreakpoints()
.filter(bp => bp.lineNumber === this.lineNumber && bp.column === this.column && bp.uri.toString() === uri.toString()).pop();
const raw: IRawBreakpoint = {
lineNumber: this.lineNumber,
column: oldBreakpoint ? oldBreakpoint.column : undefined,
enabled: true,
condition: oldBreakpoint && oldBreakpoint.condition,
hitCondition: oldBreakpoint && oldBreakpoint.hitCondition
};
if (this.hitCountContext) {
raw.hitCondition = this.inputBox.value;
if (this.conditionInput) {
raw.condition = this.conditionInput;
}
} else {
raw.condition = this.inputBox.value;
if (this.hitCountInput) {
raw.hitCondition = this.hitCountInput;
}
}
if (oldBreakpoint) {
this.debugService.removeBreakpoints(oldBreakpoint.getId()).done(null, errors.onUnexpectedError);
}
this.debugService.addBreakpoints(uri, [raw]).done(null, errors.onUnexpectedError);
}
this.dispose();
}
});
this.toDispose.push(dom.addStandardDisposableListener(this.inputBox.inputElement, 'keydown', (e: IKeyboardEvent) => {
const isEscape = e.equals(KeyCode.Escape);
const isEnter = e.equals(KeyCode.Enter);
if (isEscape || isEnter) {
e.stopPropagation();
wrapUp(isEnter);
}
}));
}
public dispose(): void {
super.dispose();
lifecycle.dispose(this.toDispose);
setTimeout(() => this.editor.focus(), 0);
}
}

View File

@@ -0,0 +1,216 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import * as lifecycle from 'vs/base/common/lifecycle';
import * as errors from 'vs/base/common/errors';
import { IAction, IActionRunner } from 'vs/base/common/actions';
import { KeyCode } from 'vs/base/common/keyCodes';
import * as dom from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { SelectActionItem, IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { EventEmitter } from 'vs/base/common/eventEmitter';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IDebugService } from 'vs/workbench/parts/debug/common/debug';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { selectBorder } from 'vs/platform/theme/common/colorRegistry';
const $ = dom.$;
export class StartDebugActionItem extends EventEmitter implements IActionItem {
private static SEPARATOR = '─────────';
public actionRunner: IActionRunner;
private container: HTMLElement;
private start: HTMLElement;
private selectBox: SelectBox;
private options: { label: string, handler: (() => boolean) }[];
private toDispose: lifecycle.IDisposable[];
private selected: number;
constructor(
private context: any,
private action: IAction,
@IDebugService private debugService: IDebugService,
@IThemeService private themeService: IThemeService,
@IConfigurationService private configurationService: IConfigurationService,
@ICommandService private commandService: ICommandService,
@IQuickOpenService private quickOpenService: IQuickOpenService
) {
super();
this.toDispose = [];
this.selectBox = new SelectBox([], -1);
this.toDispose.push(attachSelectBoxStyler(this.selectBox, themeService, {
selectBackground: SIDE_BAR_BACKGROUND
}));
this.registerListeners();
}
private registerListeners(): void {
this.toDispose.push(this.configurationService.onDidUpdateConfiguration(e => {
if (e.sourceConfig.launch) {
this.updateOptions();
}
}));
this.toDispose.push(this.selectBox.onDidSelect(e => {
if (this.options[e.index].handler()) {
this.selected = e.index;
} else {
// Some select options should not remain selected https://github.com/Microsoft/vscode/issues/31526
this.selectBox.select(this.selected);
}
}));
this.toDispose.push(this.debugService.getConfigurationManager().onDidSelectConfiguration(() => {
this.updateOptions();
}));
}
public render(container: HTMLElement): void {
this.container = container;
dom.addClass(container, 'start-debug-action-item');
this.start = dom.append(container, $('.icon'));
this.start.title = this.action.label;
this.start.tabIndex = 0;
this.toDispose.push(dom.addDisposableListener(this.start, dom.EventType.CLICK, () => {
this.start.blur();
this.actionRunner.run(this.action, this.context).done(null, errors.onUnexpectedError);
}));
this.toDispose.push(dom.addDisposableListener(this.start, dom.EventType.MOUSE_DOWN, (e: MouseEvent) => {
if (this.action.enabled && e.button === 0) {
dom.addClass(this.start, 'active');
}
}));
this.toDispose.push(dom.addDisposableListener(this.start, dom.EventType.MOUSE_UP, () => {
dom.removeClass(this.start, 'active');
}));
this.toDispose.push(dom.addDisposableListener(this.start, dom.EventType.MOUSE_OUT, () => {
dom.removeClass(this.start, 'active');
}));
this.toDispose.push(dom.addDisposableListener(this.start, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
const event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Enter)) {
this.actionRunner.run(this.action, this.context).done(null, errors.onUnexpectedError);
}
if (event.equals(KeyCode.RightArrow)) {
this.selectBox.focus();
event.stopPropagation();
}
}));
const selectBoxContainer = $('.configuration');
this.selectBox.render(dom.append(container, selectBoxContainer));
this.toDispose.push(dom.addDisposableListener(selectBoxContainer, dom.EventType.KEY_DOWN, (e: KeyboardEvent) => {
const event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.LeftArrow)) {
this.start.focus();
event.stopPropagation();
}
}));
this.toDispose.push(attachStylerCallback(this.themeService, { selectBorder }, colors => {
this.container.style.border = colors.selectBorder ? `1px solid ${colors.selectBorder}` : null;
selectBoxContainer.style.borderLeft = colors.selectBorder ? `1px solid ${colors.selectBorder}` : null;
}));
this.updateOptions();
}
public setActionContext(context: any): void {
this.context = context;
}
public isEnabled(): boolean {
return true;
}
public focus(fromRight?: boolean): void {
if (fromRight) {
this.selectBox.focus();
} else {
this.start.focus();
}
}
public blur(): void {
this.container.blur();
}
public dispose(): void {
this.toDispose = lifecycle.dispose(this.toDispose);
}
private updateOptions(): void {
this.selected = 0;
this.options = [];
const manager = this.debugService.getConfigurationManager();
const launches = manager.getLaunches();
manager.getLaunches().forEach(launch =>
launch.getConfigurationNames().forEach(name => {
if (name === manager.selectedName && launch === manager.selectedLaunch) {
this.selected = this.options.length;
}
const label = launches.length > 1 ? `${name} (${launch.name})` : name;
this.options.push({ label, handler: () => { manager.selectConfiguration(launch, name); return true; } });
}));
if (this.options.length === 0) {
this.options.push({ label: nls.localize('noConfigurations', "No Configurations"), handler: () => false });
}
this.options.push({ label: StartDebugActionItem.SEPARATOR, handler: undefined });
const disabledIdx = this.options.length - 1;
launches.forEach(l => {
const label = launches.length > 1 ? nls.localize("addConfigTo", "Add Config ({0})...", l.name) : nls.localize('addConfiguration', "Add Configuration...");
this.options.push({
label, handler: () => {
this.commandService.executeCommand('debug.addConfiguration', l.workspaceUri.toString()).done(undefined, errors.onUnexpectedError);
return false;
}
});
});
this.selectBox.setOptions(this.options.map(data => data.label), this.selected, disabledIdx);
}
}
export class FocusProcessActionItem extends SelectActionItem {
constructor(
action: IAction,
@IDebugService private debugService: IDebugService,
@IThemeService themeService: IThemeService
) {
super(null, action, [], -1);
this.toDispose.push(attachSelectBoxStyler(this.selectBox, themeService));
this.debugService.getViewModel().onDidFocusStackFrame(() => {
const process = this.debugService.getViewModel().focusedProcess;
if (process) {
const index = this.debugService.getModel().getProcesses().indexOf(process);
this.select(index);
}
});
this.debugService.getModel().onDidChangeCallStack(() => this.update());
this.update();
}
private update() {
const process = this.debugService.getViewModel().focusedProcess;
const processes = this.debugService.getModel().getProcesses();
const showRootName = this.debugService.getConfigurationManager().getLaunches().length > 1;
const names = processes.map(p => p.getName(showRootName));
this.setOptions(names, process ? processes.indexOf(process) : undefined);
}
}

View File

@@ -0,0 +1,840 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import * as lifecycle from 'vs/base/common/lifecycle';
import severity from 'vs/base/common/severity';
import { TPromise } from 'vs/base/common/winjs.base';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IFileService } from 'vs/platform/files/common/files';
import { IMessageService } from 'vs/platform/message/common/message';
import { IDebugService, State, IProcess, IThread, IEnablement, IBreakpoint, IStackFrame, IFunctionBreakpoint, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, IExpression, REPL_ID, ProcessState }
from 'vs/workbench/parts/debug/common/debug';
import { Variable, Expression, Thread, Breakpoint, Process } from 'vs/workbench/parts/debug/common/debugModel';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { TogglePanelAction } from 'vs/workbench/browser/panel';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
export abstract class AbstractDebugAction extends Action {
protected toDispose: lifecycle.IDisposable[];
constructor(
id: string, label: string, cssClass: string,
@IDebugService protected debugService: IDebugService,
@IKeybindingService private keybindingService: IKeybindingService,
public weight?: number
) {
super(id, label, cssClass, false);
this.toDispose = [];
this.toDispose.push(this.debugService.onDidChangeState(state => this.updateEnablement(state)));
this.updateLabel(label);
this.updateEnablement();
}
public run(e?: any): TPromise<any> {
throw new Error('implement me');
}
public get tooltip(): string {
const keybinding = this.keybindingService.lookupKeybinding(this.id);
const keybindingLabel = keybinding && keybinding.getLabel();
return keybindingLabel ? `${this.label} (${keybindingLabel})` : this.label;
}
protected updateLabel(newLabel: string): void {
this.label = newLabel;
}
protected updateEnablement(state = this.debugService.state): void {
this.enabled = this.isEnabled(state);
}
protected isEnabled(state: State): boolean {
return true;
}
public dispose(): void {
super.dispose();
this.toDispose = lifecycle.dispose(this.toDispose);
}
}
export class ConfigureAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.configure';
static LABEL = nls.localize('openLaunchJson', "Open {0}", 'launch.json');
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IMessageService private messageService: IMessageService
) {
super(id, label, 'debug-action configure', debugService, keybindingService);
this.toDispose.push(debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateClass()));
this.updateClass();
}
public get tooltip(): string {
if (this.debugService.getConfigurationManager().selectedName) {
return ConfigureAction.LABEL;
}
return nls.localize('launchJsonNeedsConfigurtion', "Configure or Fix 'launch.json'");
}
private updateClass(): void {
this.class = this.debugService.getConfigurationManager().selectedName ? 'debug-action configure' : 'debug-action configure notification';
}
public run(event?: any): TPromise<any> {
if (!this.contextService.hasWorkspace()) {
this.messageService.show(severity.Info, nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration."));
return TPromise.as(null);
}
const sideBySide = !!(event && (event.ctrlKey || event.metaKey));
return this.debugService.getConfigurationManager().selectedLaunch.openConfigFile(sideBySide);
}
}
export class StartAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.start';
static LABEL = nls.localize('startDebug', "Start Debugging");
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
@IWorkspaceContextService private contextService: IWorkspaceContextService
) {
super(id, label, 'debug-action start', debugService, keybindingService);
this.debugService.getConfigurationManager().onDidSelectConfiguration(() => this.updateEnablement());
this.debugService.getModel().onDidChangeCallStack(() => this.updateEnablement());
}
public run(): TPromise<any> {
const launch = this.debugService.getConfigurationManager().selectedLaunch;
return this.debugService.startDebugging(launch ? launch.workspaceUri : undefined, undefined, this.isNoDebug());
}
protected isNoDebug(): boolean {
return false;
}
// Disabled if the launch drop down shows the launch config that is already running.
protected isEnabled(state: State): boolean {
const processes = this.debugService.getModel().getProcesses();
const selectedName = this.debugService.getConfigurationManager().selectedName;
const launch = this.debugService.getConfigurationManager().selectedLaunch;
if (state === State.Initializing) {
return false;
}
if (this.contextService && !this.contextService.hasWorkspace() && processes.length > 0) {
return false;
}
if (processes.some(p => p.getName(false) === selectedName && (!launch || p.session.root.toString() === launch.workspaceUri.toString()))) {
return false;
}
const compound = launch && launch.getCompound(selectedName);
if (compound && compound.configurations && processes.some(p => compound.configurations.indexOf(p.getName(false)) !== -1)) {
return false;
}
return true;
}
}
export class RunAction extends StartAction {
static ID = 'workbench.action.debug.run';
static LABEL = nls.localize('startWithoutDebugging', "Start Without Debugging");
protected isNoDebug(): boolean {
return true;
}
}
export class SelectAndStartAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.selectandstart';
static LABEL = nls.localize('selectAndStartDebugging', "Select and Start Debugging");
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
@ICommandService commandService: ICommandService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IFileService fileService: IFileService,
@IQuickOpenService private quickOpenService: IQuickOpenService
) {
super(id, label, undefined, debugService, keybindingService);
this.quickOpenService = quickOpenService;
}
public run(): TPromise<any> {
return this.quickOpenService.show('debug ');
}
}
export class RestartAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.restart';
static LABEL = nls.localize('restartDebug', "Restart");
static RECONNECT_LABEL = nls.localize('reconnectDebug', "Reconnect");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action restart', debugService, keybindingService, 70);
this.setLabel(this.debugService.getViewModel().focusedProcess);
this.toDispose.push(this.debugService.getViewModel().onDidFocusStackFrame(() => this.setLabel(this.debugService.getViewModel().focusedProcess)));
}
private setLabel(process: IProcess): void {
this.updateLabel(process && process.state === ProcessState.ATTACH ? RestartAction.RECONNECT_LABEL : RestartAction.LABEL);
}
public run(process: IProcess): TPromise<any> {
if (!(process instanceof Process)) {
process = this.debugService.getViewModel().focusedProcess;
}
if (!process) {
return TPromise.as(null);
}
if (this.debugService.getModel().getProcesses().length <= 1) {
this.debugService.removeReplExpressions();
}
return this.debugService.restartProcess(process);
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state !== State.Inactive;
}
}
export class StepOverAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stepOver';
static LABEL = nls.localize('stepOverDebug', "Step Over");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action step-over', debugService, keybindingService, 20);
}
public run(thread: IThread): TPromise<any> {
if (!(thread instanceof Thread)) {
thread = this.debugService.getViewModel().focusedThread;
}
return thread ? thread.next() : TPromise.as(null);
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state === State.Stopped;
}
}
export class StepIntoAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stepInto';
static LABEL = nls.localize('stepIntoDebug', "Step Into");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action step-into', debugService, keybindingService, 30);
}
public run(thread: IThread): TPromise<any> {
if (!(thread instanceof Thread)) {
thread = this.debugService.getViewModel().focusedThread;
}
return thread ? thread.stepIn() : TPromise.as(null);
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state === State.Stopped;
}
}
export class StepOutAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stepOut';
static LABEL = nls.localize('stepOutDebug', "Step Out");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action step-out', debugService, keybindingService, 40);
}
public run(thread: IThread): TPromise<any> {
if (!(thread instanceof Thread)) {
thread = this.debugService.getViewModel().focusedThread;
}
return thread ? thread.stepOut() : TPromise.as(null);
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state === State.Stopped;
}
}
export class StopAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stop';
static LABEL = nls.localize('stopDebug', "Stop");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action stop', debugService, keybindingService, 80);
}
public run(process: IProcess): TPromise<any> {
if (!(process instanceof Process)) {
process = this.debugService.getViewModel().focusedProcess;
}
return this.debugService.stopProcess(process);
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state !== State.Inactive;
}
}
export class DisconnectAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.disconnect';
static LABEL = nls.localize('disconnectDebug', "Disconnect");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action disconnect', debugService, keybindingService, 80);
}
public run(): TPromise<any> {
const process = this.debugService.getViewModel().focusedProcess;
return this.debugService.stopProcess(process);
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state !== State.Inactive;
}
}
export class ContinueAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.continue';
static LABEL = nls.localize('continueDebug', "Continue");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action continue', debugService, keybindingService, 10);
}
public run(thread: IThread): TPromise<any> {
if (!(thread instanceof Thread)) {
thread = this.debugService.getViewModel().focusedThread;
}
return thread ? thread.continue() : TPromise.as(null);
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state === State.Stopped;
}
}
export class PauseAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.pause';
static LABEL = nls.localize('pauseDebug', "Pause");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action pause', debugService, keybindingService, 10);
}
public run(thread: IThread): TPromise<any> {
if (!(thread instanceof Thread)) {
thread = this.debugService.getViewModel().focusedThread;
}
return thread ? thread.pause() : TPromise.as(null);
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && state === State.Running;
}
}
export class RestartFrameAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.restartFrame';
static LABEL = nls.localize('restartFrame', "Restart Frame");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, undefined, debugService, keybindingService);
}
public run(frame: IStackFrame): TPromise<any> {
if (!frame) {
frame = this.debugService.getViewModel().focusedStackFrame;
}
return frame.restart();
}
}
export class RemoveBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.removeBreakpoint';
static LABEL = nls.localize('removeBreakpoint', "Remove Breakpoint");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action remove', debugService, keybindingService);
}
public run(breakpoint: IBreakpoint): TPromise<any> {
return breakpoint instanceof Breakpoint ? this.debugService.removeBreakpoints(breakpoint.getId())
: this.debugService.removeFunctionBreakpoints(breakpoint.getId());
}
}
export class RemoveAllBreakpointsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.removeAllBreakpoints';
static LABEL = nls.localize('removeAllBreakpoints', "Remove All Breakpoints");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action remove-all', debugService, keybindingService);
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
}
public run(): TPromise<any> {
return TPromise.join([this.debugService.removeBreakpoints(), this.debugService.removeFunctionBreakpoints()]);
}
protected isEnabled(state: State): boolean {
const model = this.debugService.getModel();
return super.isEnabled(state) && (model.getBreakpoints().length > 0 || model.getFunctionBreakpoints().length > 0);
}
}
export class EnableBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.enableBreakpoint';
static LABEL = nls.localize('enableBreakpoint', "Enable Breakpoint");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, undefined, debugService, keybindingService);
}
public run(element: IEnablement): TPromise<any> {
return this.debugService.enableOrDisableBreakpoints(true, element);
}
}
export class DisableBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.disableBreakpoint';
static LABEL = nls.localize('disableBreakpoint', "Disable Breakpoint");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, undefined, debugService, keybindingService);
}
public run(element: IEnablement): TPromise<any> {
return this.debugService.enableOrDisableBreakpoints(false, element);
}
}
export class EnableAllBreakpointsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.enableAllBreakpoints';
static LABEL = nls.localize('enableAllBreakpoints', "Enable All Breakpoints");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action enable-all-breakpoints', debugService, keybindingService);
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
}
public run(): TPromise<any> {
return this.debugService.enableOrDisableBreakpoints(true);
}
protected isEnabled(state: State): boolean {
const model = this.debugService.getModel();
return super.isEnabled(state) && (<IEnablement[]>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => !bp.enabled);
}
}
export class DisableAllBreakpointsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.disableAllBreakpoints';
static LABEL = nls.localize('disableAllBreakpoints', "Disable All Breakpoints");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action disable-all-breakpoints', debugService, keybindingService);
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
}
public run(): TPromise<any> {
return this.debugService.enableOrDisableBreakpoints(false);
}
protected isEnabled(state: State): boolean {
const model = this.debugService.getModel();
return super.isEnabled(state) && (<IEnablement[]>model.getBreakpoints()).concat(model.getFunctionBreakpoints()).concat(model.getExceptionBreakpoints()).some(bp => bp.enabled);
}
}
export class ToggleBreakpointsActivatedAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.toggleBreakpointsActivatedAction';
static ACTIVATE_LABEL = nls.localize('activateBreakpoints', "Activate Breakpoints");
static DEACTIVATE_LABEL = nls.localize('deactivateBreakpoints', "Deactivate Breakpoints");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action breakpoints-activate', debugService, keybindingService);
this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL);
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => {
this.updateLabel(this.debugService.getModel().areBreakpointsActivated() ? ToggleBreakpointsActivatedAction.DEACTIVATE_LABEL : ToggleBreakpointsActivatedAction.ACTIVATE_LABEL);
this.updateEnablement();
}));
}
public run(): TPromise<any> {
return this.debugService.setBreakpointsActivated(!this.debugService.getModel().areBreakpointsActivated());
}
protected isEnabled(state: State): boolean {
return (this.debugService.getModel().getFunctionBreakpoints().length + this.debugService.getModel().getBreakpoints().length) > 0;
}
}
export class ReapplyBreakpointsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.reapplyBreakpointsAction';
static LABEL = nls.localize('reapplyAllBreakpoints', "Reapply All Breakpoints");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, null, debugService, keybindingService);
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.updateEnablement()));
}
public run(): TPromise<any> {
return this.debugService.setBreakpointsActivated(true);
}
protected isEnabled(state: State): boolean {
const model = this.debugService.getModel();
return super.isEnabled(state) && state !== State.Inactive &&
(model.getFunctionBreakpoints().length + model.getBreakpoints().length + model.getExceptionBreakpoints().length > 0);
}
}
export class AddFunctionBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.addFunctionBreakpointAction';
static LABEL = nls.localize('addFunctionBreakpoint', "Add Function Breakpoint");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action add-function-breakpoint', debugService, keybindingService);
}
public run(): TPromise<any> {
this.debugService.addFunctionBreakpoint();
return TPromise.as(null);
}
}
export class RenameFunctionBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.renameFunctionBreakpointAction';
static LABEL = nls.localize('renameFunctionBreakpoint', "Rename Function Breakpoint");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, null, debugService, keybindingService);
}
public run(fbp: IFunctionBreakpoint): TPromise<any> {
this.debugService.getViewModel().setSelectedFunctionBreakpoint(fbp);
return TPromise.as(null);
}
}
export class AddConditionalBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.addConditionalBreakpointAction';
static LABEL = nls.localize('addConditionalBreakpoint', "Add Conditional Breakpoint...");
constructor(id: string, label: string,
private editor: ICodeEditor,
private lineNumber: number,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
) {
super(id, label, null, debugService, keybindingService);
}
public run(): TPromise<any> {
this.editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(this.lineNumber, undefined);
return TPromise.as(null);
}
}
export class EditConditionalBreakpointAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.editConditionalBreakpointAction';
static LABEL = nls.localize('editConditionalBreakpoint', "Edit Breakpoint...");
constructor(id: string, label: string,
private editor: ICodeEditor,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
) {
super(id, label, null, debugService, keybindingService);
}
public run(breakpoint: IBreakpoint): TPromise<any> {
this.editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(breakpoint.lineNumber, breakpoint.column);
return TPromise.as(null);
}
}
export class SetValueAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.setValue';
static LABEL = nls.localize('setValue', "Set Value");
constructor(id: string, label: string, private variable: Variable, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, null, debugService, keybindingService);
}
public run(): TPromise<any> {
if (this.variable instanceof Variable) {
this.debugService.getViewModel().setSelectedExpression(this.variable);
}
return TPromise.as(null);
}
protected isEnabled(state: State): boolean {
const process = this.debugService.getViewModel().focusedProcess;
return super.isEnabled(state) && state === State.Stopped && process && process.session.capabilities.supportsSetVariable;
}
}
export class AddWatchExpressionAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.addWatchExpression';
static LABEL = nls.localize('addWatchExpression', "Add Expression");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action add-watch-expression', debugService, keybindingService);
this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement()));
}
public run(): TPromise<any> {
return this.debugService.addWatchExpression();
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && this.debugService.getModel().getWatchExpressions().every(we => !!we.name);
}
}
export class EditWatchExpressionAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.editWatchExpression';
static LABEL = nls.localize('editWatchExpression', "Edit Expression");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, undefined, debugService, keybindingService);
}
public run(expression: Expression): TPromise<any> {
this.debugService.getViewModel().setSelectedExpression(expression);
return TPromise.as(null);
}
}
export class AddToWatchExpressionsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.addToWatchExpressions';
static LABEL = nls.localize('addToWatchExpressions', "Add to Watch");
constructor(id: string, label: string, private expression: IExpression, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action add-to-watch', debugService, keybindingService);
}
public run(): TPromise<any> {
const name = this.expression instanceof Variable ? this.expression.evaluateName : this.expression.name;
return this.debugService.addWatchExpression(name);
}
}
export class RemoveWatchExpressionAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.removeWatchExpression';
static LABEL = nls.localize('removeWatchExpression', "Remove Expression");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, undefined, debugService, keybindingService);
}
public run(expression: Expression): TPromise<any> {
this.debugService.removeWatchExpressions(expression.getId());
return TPromise.as(null);
}
}
export class RemoveAllWatchExpressionsAction extends AbstractDebugAction {
static ID = 'workbench.debug.viewlet.action.removeAllWatchExpressions';
static LABEL = nls.localize('removeAllWatchExpressions', "Remove All Expressions");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action remove-all', debugService, keybindingService);
this.toDispose.push(this.debugService.getModel().onDidChangeWatchExpressions(() => this.updateEnablement()));
}
public run(): TPromise<any> {
this.debugService.removeWatchExpressions();
return TPromise.as(null);
}
protected isEnabled(state: State): boolean {
return super.isEnabled(state) && this.debugService.getModel().getWatchExpressions().length > 0;
}
}
export class ClearReplAction extends AbstractDebugAction {
static ID = 'workbench.debug.panel.action.clearReplAction';
static LABEL = nls.localize('clearRepl', "Clear Console");
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
@IPanelService private panelService: IPanelService
) {
super(id, label, 'debug-action clear-repl', debugService, keybindingService);
}
public run(): TPromise<any> {
this.debugService.removeReplExpressions();
// focus back to repl
return this.panelService.openPanel(REPL_ID, true);
}
}
export class ToggleReplAction extends TogglePanelAction {
static ID = 'workbench.debug.action.toggleRepl';
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugConsoleAction' }, 'Debug Console');
private toDispose: lifecycle.IDisposable[];
constructor(id: string, label: string,
@IDebugService private debugService: IDebugService,
@IPartService partService: IPartService,
@IPanelService panelService: IPanelService
) {
super(id, label, REPL_ID, panelService, partService, 'debug-action toggle-repl');
this.toDispose = [];
this.registerListeners();
}
private registerListeners(): void {
this.toDispose.push(this.debugService.getModel().onDidChangeReplElements(() => {
if (!this.isReplVisible()) {
this.class = 'debug-action toggle-repl notification';
this.tooltip = nls.localize('unreadOutput', "New Output in Debug Console");
}
}));
this.toDispose.push(this.panelService.onDidPanelOpen(panel => {
if (panel.getId() === REPL_ID) {
this.class = 'debug-action toggle-repl';
this.tooltip = ToggleReplAction.LABEL;
}
}));
}
private isReplVisible(): boolean {
const panel = this.panelService.getActivePanel();
return panel && panel.getId() === REPL_ID;
}
public dispose(): void {
super.dispose();
this.toDispose = lifecycle.dispose(this.toDispose);
}
}
export class FocusReplAction extends Action {
static ID = 'workbench.debug.action.focusRepl';
static LABEL = nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugFocusConsole' }, 'Focus Debug Console');
constructor(id: string, label: string,
@IPanelService private panelService: IPanelService
) {
super(id, label);
}
public run(): TPromise<any> {
return this.panelService.openPanel(REPL_ID, true);
}
}
export class FocusProcessAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.focusProcess';
static LABEL = nls.localize('focusProcess', "Focus Process");
constructor(id: string, label: string,
@IDebugService debugService: IDebugService,
@IKeybindingService keybindingService: IKeybindingService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
) {
super(id, label, null, debugService, keybindingService, 100);
}
public run(processName: string): TPromise<any> {
const isMultiRoot = this.debugService.getConfigurationManager().getLaunches().length > 1;
const process = this.debugService.getModel().getProcesses().filter(p => p.getName(isMultiRoot) === processName).pop();
return this.debugService.focusStackFrameAndEvaluate(null, process, true).then(() => {
const stackFrame = this.debugService.getViewModel().focusedStackFrame;
if (stackFrame) {
return stackFrame.openInEditor(this.editorService, true);
}
return undefined;
});
}
}
// Actions used by the chakra debugger
export class StepBackAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.stepBack';
static LABEL = nls.localize('stepBackDebug', "Step Back");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action step-back', debugService, keybindingService, 50);
}
public run(thread: IThread): TPromise<any> {
if (!(thread instanceof Thread)) {
thread = this.debugService.getViewModel().focusedThread;
}
return thread ? thread.stepBack() : TPromise.as(null);
}
protected isEnabled(state: State): boolean {
const process = this.debugService.getViewModel().focusedProcess;
return super.isEnabled(state) && state === State.Stopped &&
process && process.session.capabilities.supportsStepBack;
}
}
export class ReverseContinueAction extends AbstractDebugAction {
static ID = 'workbench.action.debug.reverseContinue';
static LABEL = nls.localize('reverseContinue', "Reverse");
constructor(id: string, label: string, @IDebugService debugService: IDebugService, @IKeybindingService keybindingService: IKeybindingService) {
super(id, label, 'debug-action reverse-continue', debugService, keybindingService, 60);
}
public run(thread: IThread): TPromise<any> {
if (!(thread instanceof Thread)) {
thread = this.debugService.getViewModel().focusedThread;
}
return thread ? thread.reverseContinue() : TPromise.as(null);
}
protected isEnabled(state: State): boolean {
const process = this.debugService.getViewModel().focusedProcess;
return super.isEnabled(state) && state === State.Stopped &&
process && process.session.capabilities.supportsStepBack;
}
}

View File

@@ -0,0 +1,278 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!vs/workbench/parts/debug/browser/media/debugActionsWidget';
import * as errors from 'vs/base/common/errors';
import * as strings from 'vs/base/common/strings';
import * as browser from 'vs/base/browser/browser';
import severity from 'vs/base/common/severity';
import * as builder from 'vs/base/browser/builder';
import * as dom from 'vs/base/browser/dom';
import * as arrays from 'vs/base/common/arrays';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { IAction } from 'vs/base/common/actions';
import { EventType } from 'vs/base/common/events';
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IDebugConfiguration, IDebugService, State } from 'vs/workbench/parts/debug/common/debug';
import { AbstractDebugAction, PauseAction, ContinueAction, StepBackAction, ReverseContinueAction, StopAction, DisconnectAction, StepOverAction, StepIntoAction, StepOutAction, RestartAction, FocusProcessAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { FocusProcessActionItem } from 'vs/workbench/parts/debug/browser/debugActionItems';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IMessageService } from 'vs/platform/message/common/message';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Themable } from 'vs/workbench/common/theme';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { registerColor, contrastBorder, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
import { localize } from 'vs/nls';
const $ = builder.$;
const DEBUG_ACTIONS_WIDGET_POSITION_KEY = 'debug.actionswidgetposition';
export const debugToolBarBackground = registerColor('debugToolBar.background', {
dark: '#333333',
light: '#F3F3F3',
hc: '#000000'
}, localize('debugToolBarBackground', "Debug toolbar background color."));
export class DebugActionsWidget extends Themable implements IWorkbenchContribution {
private static ID = 'debug.actionsWidget';
private $el: builder.Builder;
private dragArea: builder.Builder;
private actionBar: ActionBar;
private allActions: AbstractDebugAction[];
private activeActions: AbstractDebugAction[];
private isVisible: boolean;
private isBuilt: boolean;
constructor(
@IMessageService private messageService: IMessageService,
@ITelemetryService private telemetryService: ITelemetryService,
@IDebugService private debugService: IDebugService,
@IInstantiationService private instantiationService: IInstantiationService,
@IPartService private partService: IPartService,
@IStorageService private storageService: IStorageService,
@IConfigurationService private configurationService: IConfigurationService,
@IThemeService themeService: IThemeService
) {
super(themeService);
this.$el = $().div().addClass('debug-actions-widget').style('top', `${partService.getTitleBarOffset()}px`);
this.dragArea = $().div().addClass('drag-area');
this.$el.append(this.dragArea);
const actionBarContainter = $().div().addClass('.action-bar-container');
this.$el.append(actionBarContainter);
this.activeActions = [];
this.actionBar = new ActionBar(actionBarContainter, {
orientation: ActionsOrientation.HORIZONTAL,
actionItemProvider: (action: IAction) => {
if (action.id === FocusProcessAction.ID) {
return this.instantiationService.createInstance(FocusProcessActionItem, action);
}
return null;
}
});
this.updateStyles();
this.toUnbind.push(this.actionBar);
this.registerListeners();
this.hide();
this.isBuilt = false;
}
private registerListeners(): void {
this.toUnbind.push(this.debugService.onDidChangeState(state => this.update(state)));
this.toUnbind.push(this.configurationService.onDidUpdateConfiguration(() => this.update(this.debugService.state)));
this.toUnbind.push(this.actionBar.actionRunner.addListener(EventType.RUN, (e: any) => {
// check for error
if (e.error && !errors.isPromiseCanceledError(e.error)) {
this.messageService.show(severity.Error, e.error);
}
// log in telemetry
if (this.telemetryService) {
this.telemetryService.publicLog('workbenchActionExecuted', { id: e.action.id, from: 'debugActionsWidget' });
}
}));
$(window).on(dom.EventType.RESIZE, () => this.setXCoordinate(), this.toUnbind);
this.dragArea.on(dom.EventType.MOUSE_UP, (event: MouseEvent) => {
const mouseClickEvent = new StandardMouseEvent(event);
if (mouseClickEvent.detail === 2) {
// double click on debug bar centers it again #8250
const widgetWidth = this.$el.getHTMLElement().clientWidth;
this.setXCoordinate(0.5 * window.innerWidth - 0.5 * widgetWidth);
this.storePosition();
}
});
this.dragArea.on(dom.EventType.MOUSE_DOWN, (event: MouseEvent) => {
const $window = $(window);
this.dragArea.addClass('dragged');
$window.on('mousemove', (e: MouseEvent) => {
const mouseMoveEvent = new StandardMouseEvent(e);
// Prevent default to stop editor selecting text #8524
mouseMoveEvent.preventDefault();
// Reduce x by width of drag handle to reduce jarring #16604
this.setXCoordinate(mouseMoveEvent.posx - 14);
}).once('mouseup', (e: MouseEvent) => {
this.storePosition();
this.dragArea.removeClass('dragged');
$window.off('mousemove');
});
});
this.toUnbind.push(this.partService.onTitleBarVisibilityChange(() => this.positionDebugWidget()));
this.toUnbind.push(browser.onDidChangeZoomLevel(() => this.positionDebugWidget()));
}
private storePosition(): void {
const position = parseFloat(this.$el.getComputedStyle().left) / window.innerWidth;
this.storageService.store(DEBUG_ACTIONS_WIDGET_POSITION_KEY, position, StorageScope.WORKSPACE);
this.telemetryService.publicLog(DEBUG_ACTIONS_WIDGET_POSITION_KEY, { position });
}
protected updateStyles(): void {
super.updateStyles();
if (this.$el) {
this.$el.style('background-color', this.getColor(debugToolBarBackground));
const widgetShadowColor = this.getColor(widgetShadow);
this.$el.style('box-shadow', widgetShadowColor ? `0 5px 8px ${widgetShadowColor}` : null);
const contrastBorderColor = this.getColor(contrastBorder);
this.$el.style('border-style', contrastBorderColor ? 'solid' : null);
this.$el.style('border-width', contrastBorderColor ? '1px' : null);
this.$el.style('border-color', contrastBorderColor);
}
}
private positionDebugWidget(): void {
const titlebarOffset = this.partService.getTitleBarOffset();
$(this.$el).style('top', `${titlebarOffset}px`);
}
private setXCoordinate(x?: number): void {
if (!this.isVisible) {
return;
}
const widgetWidth = this.$el.getHTMLElement().clientWidth;
if (x === undefined) {
const positionPercentage = this.storageService.get(DEBUG_ACTIONS_WIDGET_POSITION_KEY, StorageScope.WORKSPACE);
x = positionPercentage !== undefined ? parseFloat(positionPercentage) * window.innerWidth : (0.5 * window.innerWidth - 0.5 * widgetWidth);
}
x = Math.max(0, Math.min(x, window.innerWidth - widgetWidth)); // do not allow the widget to overflow on the right
this.$el.style('left', `${x}px`);
}
public getId(): string {
return DebugActionsWidget.ID;
}
private update(state: State): void {
if (state === State.Inactive || this.configurationService.getConfiguration<IDebugConfiguration>('debug').hideActionBar) {
return this.hide();
}
const actions = this.getActions();
if (!arrays.equals(actions, this.activeActions, (first, second) => first.id === second.id)) {
this.actionBar.clear();
this.actionBar.push(actions, { icon: true, label: false });
this.activeActions = actions;
}
this.show();
}
private show(): void {
if (this.isVisible) {
return;
}
if (!this.isBuilt) {
this.isBuilt = true;
this.$el.build(builder.withElementById(this.partService.getWorkbenchElementId()).getHTMLElement());
}
this.isVisible = true;
this.$el.show();
this.setXCoordinate();
}
private hide(): void {
this.isVisible = false;
this.$el.hide();
}
private getActions(): AbstractDebugAction[] {
if (!this.allActions) {
this.allActions = [];
this.allActions.push(this.instantiationService.createInstance(ContinueAction, ContinueAction.ID, ContinueAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(PauseAction, PauseAction.ID, PauseAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(StopAction, StopAction.ID, StopAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(DisconnectAction, DisconnectAction.ID, DisconnectAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(StepOverAction, StepOverAction.ID, StepOverAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(StepIntoAction, StepIntoAction.ID, StepIntoAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(StepOutAction, StepOutAction.ID, StepOutAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(RestartAction, RestartAction.ID, RestartAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(StepBackAction, StepBackAction.ID, StepBackAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(ReverseContinueAction, ReverseContinueAction.ID, ReverseContinueAction.LABEL));
this.allActions.push(this.instantiationService.createInstance(FocusProcessAction, FocusProcessAction.ID, FocusProcessAction.LABEL));
this.allActions.forEach(a => {
this.toUnbind.push(a);
});
}
const state = this.debugService.state;
const process = this.debugService.getViewModel().focusedProcess;
const attached = process && process.configuration.request === 'attach' && process.configuration.type && !strings.equalsIgnoreCase(process.configuration.type, 'extensionHost');
return this.allActions.filter(a => {
if (a.id === ContinueAction.ID) {
return state !== State.Running;
}
if (a.id === PauseAction.ID) {
return state === State.Running;
}
if (a.id === StepBackAction.ID) {
return process && process.session.capabilities.supportsStepBack;
}
if (a.id === ReverseContinueAction.ID) {
return process && process.session.capabilities.supportsStepBack;
}
if (a.id === DisconnectAction.ID) {
return attached;
}
if (a.id === StopAction.ID) {
return !attached;
}
if (a.id === FocusProcessAction.ID) {
return this.debugService.getViewModel().isMultiProcessView();
}
return true;
}).sort((first, second) => first.weight - second.weight);
}
public dispose(): void {
super.dispose();
if (this.$el) {
this.$el.destroy();
delete this.$el;
}
}
}

View File

@@ -0,0 +1,77 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import uri from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import { guessMimeTypes, MIME_TEXT } from 'vs/base/common/mime';
import { IModel } from 'vs/editor/common/editorCommon';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { DEBUG_SCHEME, IDebugService, IProcess } from 'vs/workbench/parts/debug/common/debug';
export class DebugContentProvider implements IWorkbenchContribution, ITextModelContentProvider {
constructor(
@ITextModelService textModelResolverService: ITextModelService,
@IDebugService private debugService: IDebugService,
@IModelService private modelService: IModelService,
@IModeService private modeService: IModeService
) {
textModelResolverService.registerTextModelContentProvider(DEBUG_SCHEME, this);
}
public getId(): string {
return 'debug.contentprovider';
}
public provideTextContent(resource: uri): TPromise<IModel> {
let process: IProcess;
if (resource.query) {
const keyvalues = resource.query.split('&');
for (let keyvalue of keyvalues) {
const pair = keyvalue.split('=');
if (pair.length === 2 && pair[0] === 'session') {
process = this.debugService.findProcessByUUID(decodeURIComponent(pair[1]));
break;
}
}
}
if (!process) {
// fallback: use focused process
process = this.debugService.getViewModel().focusedProcess;
}
if (!process) {
return TPromise.wrapError<IModel>(new Error(localize('unable', "Unable to resolve the resource without a debug session")));
}
const source = process.sources.get(resource.toString());
let rawSource: DebugProtocol.Source;
if (source) {
rawSource = source.raw;
} else {
// Remove debug: scheme
rawSource = { path: resource.with({ scheme: '', query: '' }).toString(true) };
}
return process.session.source({ sourceReference: source ? source.reference : undefined, source: rawSource }).then(response => {
const mime = response.body.mimeType || guessMimeTypes(resource.toString())[0];
const modePromise = this.modeService.getOrCreateMode(mime);
const model = this.modelService.createModel(response.body.content, modePromise, resource);
return model;
}, (err: DebugProtocol.ErrorResponse) => {
this.debugService.sourceIsNotAvailable(resource);
const modePromise = this.modeService.getOrCreateMode(MIME_TEXT);
const model = this.modelService.createModel(err.message, modePromise, resource);
return model;
});
}
}

View File

@@ -0,0 +1,277 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { Range } from 'vs/editor/common/core/range';
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ServicesAccessor, editorAction, EditorAction, CommonEditorRegistry, EditorCommand } from 'vs/editor/common/editorCommonExtensions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IDebugService, CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL, CONTEXT_DEBUG_STATE, State, REPL_ID, VIEWLET_ID, IDebugEditorContribution, EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINT_WIDGET_VISIBLE } from 'vs/workbench/parts/debug/common/debug';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
@editorAction
class ToggleBreakpointAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.toggleBreakpoint',
label: nls.localize('toggleBreakpointAction', "Debug: Toggle Breakpoint"),
alias: 'Debug: Toggle Breakpoint',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.textFocus,
primary: KeyCode.F9
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise<any> {
const debugService = accessor.get(IDebugService);
const position = editor.getPosition();
const modelUri = editor.getModel().uri;
const bps = debugService.getModel().getBreakpoints()
.filter(bp => bp.lineNumber === position.lineNumber && bp.uri.toString() === modelUri.toString());
if (bps.length) {
return TPromise.join(bps.map(bp => debugService.removeBreakpoints(bp.getId())));
}
if (debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) {
return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber }]);
}
return TPromise.as(null);
}
}
function addColumnBreakpoint(accessor: ServicesAccessor, editor: ICommonCodeEditor, remove: boolean): TPromise<any> {
const debugService = accessor.get(IDebugService);
const position = editor.getPosition();
const modelUri = editor.getModel().uri;
const bp = debugService.getModel().getBreakpoints()
.filter(bp => bp.lineNumber === position.lineNumber && bp.column === position.column && bp.uri.toString() === modelUri.toString()).pop();
if (bp) {
return remove ? debugService.removeBreakpoints(bp.getId()) : TPromise.as(null);
}
if (debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) {
return debugService.addBreakpoints(modelUri, [{ lineNumber: position.lineNumber, column: position.column }]);
}
return TPromise.as(null);
}
@editorAction
class ToggleColumnBreakpointAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.toggleColumnBreakpoint',
label: nls.localize('columnBreakpointAction', "Debug: Column Breakpoint"),
alias: 'Debug: Column Breakpoint',
precondition: null,
kbOpts: {
kbExpr: EditorContextKeys.textFocus,
primary: KeyMod.Shift | KeyCode.F9
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise<any> {
return addColumnBreakpoint(accessor, editor, true);
}
}
// TODO@Isidor merge two column breakpoints actions together
@editorAction
class ToggleColumnBreakpointContextMenuAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.toggleColumnBreakpointContextMenu',
label: nls.localize('columnBreakpoint', "Add Column Breakpoint"),
alias: 'Toggle Column Breakpoint',
precondition: ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL, EditorContextKeys.writable),
menuOpts: {
group: 'debug',
order: 1
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise<any> {
return addColumnBreakpoint(accessor, editor, false);
}
}
@editorAction
class ConditionalBreakpointAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.conditionalBreakpoint',
label: nls.localize('conditionalBreakpointEditorAction', "Debug: Add Conditional Breakpoint..."),
alias: 'Debug: Add Conditional Breakpoint...',
precondition: null
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): void {
const debugService = accessor.get(IDebugService);
const { lineNumber, column } = editor.getPosition();
if (debugService.getConfigurationManager().canSetBreakpointsIn(editor.getModel())) {
editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(lineNumber, column);
}
}
}
@editorAction
class RunToCursorAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.runToCursor',
label: nls.localize('runToCursor', "Run to Cursor"),
alias: 'Debug: Run to Cursor',
precondition: ContextKeyExpr.and(CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL, EditorContextKeys.writable, CONTEXT_DEBUG_STATE.isEqualTo('stopped')),
menuOpts: {
group: 'debug',
order: 2
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise<void> {
const debugService = accessor.get(IDebugService);
if (debugService.state !== State.Stopped) {
return TPromise.as(null);
}
const position = editor.getPosition();
const uri = editor.getModel().uri;
const oneTimeListener = debugService.getViewModel().focusedProcess.session.onDidEvent(event => {
if (event.event === 'stopped' || event.event === 'exit') {
const toRemove = debugService.getModel().getBreakpoints()
.filter(bp => bp.lineNumber === position.lineNumber && bp.uri.toString() === uri.toString()).pop();
if (toRemove) {
debugService.removeBreakpoints(toRemove.getId());
}
oneTimeListener.dispose();
}
});
const bpExists = !!(debugService.getModel().getBreakpoints().filter(bp => bp.column === position.column && bp.lineNumber === position.lineNumber && bp.uri.toString() === uri.toString()).pop());
return (bpExists ? TPromise.as(null) : debugService.addBreakpoints(uri, [{ lineNumber: position.lineNumber, column: position.column }])).then(() => {
debugService.getViewModel().focusedThread.continue();
});
}
}
@editorAction
class SelectionToReplAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.selectionToRepl',
label: nls.localize('debugEvaluate', "Debug: Evaluate"),
alias: 'Debug: Evaluate',
precondition: ContextKeyExpr.and(EditorContextKeys.hasNonEmptySelection, CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL),
menuOpts: {
group: 'debug',
order: 0
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise<void> {
const debugService = accessor.get(IDebugService);
const panelService = accessor.get(IPanelService);
const text = editor.getModel().getValueInRange(editor.getSelection());
return debugService.addReplExpression(text)
.then(() => panelService.openPanel(REPL_ID, true))
.then(_ => void 0);
}
}
@editorAction
class SelectionToWatchExpressionsAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.selectionToWatch',
label: nls.localize('debugAddToWatch', "Debug: Add to Watch"),
alias: 'Debug: Add to Watch',
precondition: ContextKeyExpr.and(EditorContextKeys.hasNonEmptySelection, CONTEXT_IN_DEBUG_MODE, CONTEXT_NOT_IN_DEBUG_REPL),
menuOpts: {
group: 'debug',
order: 1
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise<void> {
const debugService = accessor.get(IDebugService);
const viewletService = accessor.get(IViewletService);
const text = editor.getModel().getValueInRange(editor.getSelection());
return viewletService.openViewlet(VIEWLET_ID).then(() => debugService.addWatchExpression(text));
}
}
@editorAction
class ShowDebugHoverAction extends EditorAction {
constructor() {
super({
id: 'editor.debug.action.showDebugHover',
label: nls.localize('showDebugHover', "Debug: Show Hover"),
alias: 'Debug: Show Hover',
precondition: CONTEXT_IN_DEBUG_MODE,
kbOpts: {
kbExpr: EditorContextKeys.textFocus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_I)
}
});
}
public run(accessor: ServicesAccessor, editor: ICommonCodeEditor): TPromise<void> {
const position = editor.getPosition();
const word = editor.getModel().getWordAtPosition(position);
if (!word) {
return TPromise.as(null);
}
const range = new Range(position.lineNumber, position.column, position.lineNumber, word.endColumn);
return editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showHover(range, true);
}
}
class CloseBreakpointWidgetCommand extends EditorCommand {
constructor() {
super({
id: 'closeBreakpointWidget',
precondition: CONTEXT_BREAKPOINT_WIDGET_VISIBLE,
kbOpts: {
weight: CommonEditorRegistry.commandWeight(8),
kbExpr: EditorContextKeys.focus,
primary: KeyCode.Escape,
secondary: [KeyMod.Shift | KeyCode.Escape]
}
});
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICommonCodeEditor, args: any): void {
return editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).closeBreakpointWidget();
}
}
CommonEditorRegistry.registerEditorCommand(new CloseBreakpointWidgetCommand());

View File

@@ -0,0 +1,387 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import * as objects from 'vs/base/common/objects';
import * as lifecycle from 'vs/base/common/lifecycle';
import { Constants } from 'vs/editor/common/core/uint';
import { Range } from 'vs/editor/common/core/range';
import { IModel, TrackedRangeStickiness, IModelDeltaDecoration, IModelDecorationOptions } from 'vs/editor/common/editorCommon';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IDebugService, IBreakpoint, IRawBreakpoint, State } from 'vs/workbench/parts/debug/common/debug';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents';
import { MarkdownString } from 'vs/base/common/htmlContent';
interface IDebugEditorModelData {
model: IModel;
toDispose: lifecycle.IDisposable[];
breakpointDecorationIds: string[];
breakpointLines: number[];
breakpointDecorationsAsMap: Map<string, boolean>;
currentStackDecorations: string[];
dirty: boolean;
topStackFrameRange: Range;
}
const stickiness = TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges;
export class DebugEditorModelManager implements IWorkbenchContribution {
static ID = 'breakpointManager';
private modelDataMap: Map<string, IDebugEditorModelData>;
private toDispose: lifecycle.IDisposable[];
constructor(
@IModelService private modelService: IModelService,
@IDebugService private debugService: IDebugService
) {
this.modelDataMap = new Map<string, IDebugEditorModelData>();
this.toDispose = [];
this.registerListeners();
}
public getId(): string {
return DebugEditorModelManager.ID;
}
public dispose(): void {
this.modelDataMap.forEach(modelData => {
lifecycle.dispose(modelData.toDispose);
modelData.model.deltaDecorations(modelData.breakpointDecorationIds, []);
modelData.model.deltaDecorations(modelData.currentStackDecorations, []);
});
this.toDispose = lifecycle.dispose(this.toDispose);
this.modelDataMap.clear();
}
private registerListeners(): void {
this.toDispose.push(this.modelService.onModelAdded(this.onModelAdded, this));
this.modelService.getModels().forEach(model => this.onModelAdded(model));
this.toDispose.push(this.modelService.onModelRemoved(this.onModelRemoved, this));
this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => this.onBreakpointsChange()));
this.toDispose.push(this.debugService.getViewModel().onDidFocusStackFrame(() => this.onFocusStackFrame()));
this.toDispose.push(this.debugService.onDidChangeState(state => {
if (state === State.Inactive) {
this.modelDataMap.forEach(modelData => {
modelData.dirty = false;
modelData.topStackFrameRange = undefined;
});
}
}));
}
private onModelAdded(model: IModel): void {
const modelUrlStr = model.uri.toString();
const breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp.uri.toString() === modelUrlStr);
const currentStackDecorations = model.deltaDecorations([], this.createCallStackDecorations(modelUrlStr));
const breakPointDecorations = model.deltaDecorations([], this.createBreakpointDecorations(breakpoints));
const toDispose: lifecycle.IDisposable[] = [model.onDidChangeDecorations((e) => this.onModelDecorationsChanged(modelUrlStr, e))];
const breakpointDecorationsAsMap = new Map<string, boolean>();
breakPointDecorations.forEach(bpd => breakpointDecorationsAsMap.set(bpd, true));
this.modelDataMap.set(modelUrlStr, {
model: model,
toDispose: toDispose,
breakpointDecorationIds: breakPointDecorations,
breakpointLines: breakpoints.map(bp => bp.lineNumber),
breakpointDecorationsAsMap,
currentStackDecorations: currentStackDecorations,
dirty: false,
topStackFrameRange: undefined
});
}
private onModelRemoved(model: IModel): void {
const modelUriStr = model.uri.toString();
if (this.modelDataMap.has(modelUriStr)) {
lifecycle.dispose(this.modelDataMap.get(modelUriStr).toDispose);
this.modelDataMap.delete(modelUriStr);
}
}
// call stack management. Represent data coming from the debug service.
private onFocusStackFrame(): void {
this.modelDataMap.forEach((modelData, uri) => {
modelData.currentStackDecorations = modelData.model.deltaDecorations(modelData.currentStackDecorations, this.createCallStackDecorations(uri));
});
}
private createCallStackDecorations(modelUriStr: string): IModelDeltaDecoration[] {
const result: IModelDeltaDecoration[] = [];
const stackFrame = this.debugService.getViewModel().focusedStackFrame;
if (!stackFrame || stackFrame.source.uri.toString() !== modelUriStr) {
return result;
}
// only show decorations for the currently focused thread.
const columnUntilEOLRange = new Range(stackFrame.range.startLineNumber, stackFrame.range.startColumn, stackFrame.range.startLineNumber, Constants.MAX_SAFE_SMALL_INTEGER);
const range = new Range(stackFrame.range.startLineNumber, stackFrame.range.startColumn, stackFrame.range.startLineNumber, stackFrame.range.startColumn + 1);
// compute how to decorate the editor. Different decorations are used if this is a top stack frame, focused stack frame,
// an exception or a stack frame that did not change the line number (we only decorate the columns, not the whole line).
const callStack = stackFrame.thread.getCallStack();
if (callStack && callStack.length && stackFrame === callStack[0]) {
result.push({
options: DebugEditorModelManager.TOP_STACK_FRAME_MARGIN,
range
});
if (stackFrame.thread.stoppedDetails && stackFrame.thread.stoppedDetails.reason === 'exception') {
result.push({
options: DebugEditorModelManager.TOP_STACK_FRAME_EXCEPTION_DECORATION,
range: columnUntilEOLRange
});
} else {
result.push({
options: DebugEditorModelManager.TOP_STACK_FRAME_DECORATION,
range: columnUntilEOLRange
});
if (stackFrame.range.endLineNumber && stackFrame.range.endColumn) {
result.push({
options: { className: 'debug-top-stack-frame-range' },
range: stackFrame.range
});
}
if (this.modelDataMap.has(modelUriStr)) {
const modelData = this.modelDataMap.get(modelUriStr);
if (modelData.topStackFrameRange && modelData.topStackFrameRange.startLineNumber === stackFrame.range.startLineNumber && modelData.topStackFrameRange.startColumn !== stackFrame.range.startColumn) {
result.push({
options: DebugEditorModelManager.TOP_STACK_FRAME_INLINE_DECORATION,
range: columnUntilEOLRange
});
}
modelData.topStackFrameRange = columnUntilEOLRange;
}
}
} else {
result.push({
options: DebugEditorModelManager.FOCUSED_STACK_FRAME_MARGIN,
range
});
if (stackFrame.range.endLineNumber && stackFrame.range.endColumn) {
result.push({
options: { className: 'debug-focused-stack-frame-range' },
range: stackFrame.range
});
}
result.push({
options: DebugEditorModelManager.FOCUSED_STACK_FRAME_DECORATION,
range: columnUntilEOLRange
});
}
return result;
}
// breakpoints management. Represent data coming from the debug service and also send data back.
private onModelDecorationsChanged(modelUrlStr: string, e: IModelDecorationsChangedEvent): void {
const modelData = this.modelDataMap.get(modelUrlStr);
if (modelData.breakpointDecorationsAsMap.size === 0) {
// I have no decorations
return;
}
if (!e.changedDecorations.some(decorationId => modelData.breakpointDecorationsAsMap.has(decorationId))) {
// nothing to do, my decorations did not change.
return;
}
const data: IRawBreakpoint[] = [];
const lineToBreakpointDataMap = new Map<number, IBreakpoint>();
this.debugService.getModel().getBreakpoints().filter(bp => bp.uri.toString() === modelUrlStr).forEach(bp => {
lineToBreakpointDataMap.set(bp.lineNumber, bp);
});
const modelUri = modelData.model.uri;
for (let i = 0, len = modelData.breakpointDecorationIds.length; i < len; i++) {
const decorationRange = modelData.model.getDecorationRange(modelData.breakpointDecorationIds[i]);
const lineNumber = modelData.breakpointLines[i];
// check if the line got deleted.
if (decorationRange.endColumn - decorationRange.startColumn > 0) {
const breakpoint = lineToBreakpointDataMap.get(lineNumber);
// since we know it is collapsed, it cannot grow to multiple lines
data.push({
lineNumber: decorationRange.startLineNumber,
enabled: breakpoint.enabled,
condition: breakpoint.condition,
hitCondition: breakpoint.hitCondition,
column: breakpoint.column ? decorationRange.startColumn : undefined
});
}
}
modelData.dirty = this.debugService.state !== State.Inactive;
const toRemove = this.debugService.getModel().getBreakpoints()
.filter(bp => bp.uri.toString() === modelUri.toString());
TPromise.join(toRemove.map(bp => this.debugService.removeBreakpoints(bp.getId()))).then(() => {
this.debugService.addBreakpoints(modelUri, data);
});
}
private onBreakpointsChange(): void {
const breakpointsMap = new Map<string, IBreakpoint[]>();
this.debugService.getModel().getBreakpoints().forEach(bp => {
const uriStr = bp.uri.toString();
if (breakpointsMap.has(uriStr)) {
breakpointsMap.get(uriStr).push(bp);
} else {
breakpointsMap.set(uriStr, [bp]);
}
});
breakpointsMap.forEach((bps, uri) => {
if (this.modelDataMap.has(uri)) {
this.updateBreakpoints(this.modelDataMap.get(uri), breakpointsMap.get(uri));
}
});
this.modelDataMap.forEach((modelData, uri) => {
if (!breakpointsMap.has(uri)) {
this.updateBreakpoints(modelData, []);
}
});
}
private updateBreakpoints(modelData: IDebugEditorModelData, newBreakpoints: IBreakpoint[]): void {
modelData.breakpointDecorationIds = modelData.model.deltaDecorations(modelData.breakpointDecorationIds, this.createBreakpointDecorations(newBreakpoints));
modelData.breakpointDecorationsAsMap.clear();
modelData.breakpointDecorationIds.forEach(id => modelData.breakpointDecorationsAsMap.set(id, true));
modelData.breakpointLines = newBreakpoints.map(bp => bp.lineNumber);
}
private createBreakpointDecorations(breakpoints: IBreakpoint[]): IModelDeltaDecoration[] {
return breakpoints.map((breakpoint) => {
const range = breakpoint.column ? new Range(breakpoint.lineNumber, breakpoint.column, breakpoint.lineNumber, breakpoint.column + 1)
: new Range(breakpoint.lineNumber, 1, breakpoint.lineNumber, Constants.MAX_SAFE_SMALL_INTEGER); // Decoration has to have a width #20688
return {
options: this.getBreakpointDecorationOptions(breakpoint),
range
};
});
}
private getBreakpointDecorationOptions(breakpoint: IBreakpoint): IModelDecorationOptions {
const activated = this.debugService.getModel().areBreakpointsActivated();
const state = this.debugService.state;
const debugActive = state === State.Running || state === State.Stopped || state === State.Initializing;
const modelData = this.modelDataMap.get(breakpoint.uri.toString());
let result = (!breakpoint.enabled || !activated) ? DebugEditorModelManager.BREAKPOINT_DISABLED_DECORATION :
debugActive && modelData && modelData.dirty && !breakpoint.verified ? DebugEditorModelManager.BREAKPOINT_DIRTY_DECORATION :
debugActive && !breakpoint.verified ? DebugEditorModelManager.BREAKPOINT_UNVERIFIED_DECORATION :
!breakpoint.condition && !breakpoint.hitCondition ? DebugEditorModelManager.BREAKPOINT_DECORATION : null;
if (result) {
result = objects.clone(result);
if (breakpoint.message) {
result.glyphMarginHoverMessage = new MarkdownString().appendText(breakpoint.message);
}
if (breakpoint.column) {
result.beforeContentClassName = `debug-breakpoint-column ${result.glyphMarginClassName}-column`;
}
return result;
}
const process = this.debugService.getViewModel().focusedProcess;
if (process && !process.session.capabilities.supportsConditionalBreakpoints) {
return DebugEditorModelManager.BREAKPOINT_UNSUPPORTED_DECORATION;
}
const modeId = modelData ? modelData.model.getLanguageIdentifier().language : '';
let condition: string;
if (breakpoint.condition && breakpoint.hitCondition) {
condition = `Expression: ${breakpoint.condition}\nHitCount: ${breakpoint.hitCondition}`;
} else {
condition = breakpoint.condition ? breakpoint.condition : breakpoint.hitCondition;
}
const glyphMarginHoverMessage = new MarkdownString().appendCodeblock(modeId, condition);
const glyphMarginClassName = 'debug-breakpoint-conditional-glyph';
const beforeContentClassName = breakpoint.column ? `debug-breakpoint-column ${glyphMarginClassName}-column` : undefined;
return {
glyphMarginClassName,
glyphMarginHoverMessage,
stickiness,
beforeContentClassName
};
}
// editor decorations
private static BREAKPOINT_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-glyph',
stickiness
};
private static BREAKPOINT_DISABLED_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-disabled-glyph',
glyphMarginHoverMessage: new MarkdownString().appendText(nls.localize('breakpointDisabledHover', "Disabled Breakpoint")),
stickiness
};
private static BREAKPOINT_UNVERIFIED_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-unverified-glyph',
glyphMarginHoverMessage: new MarkdownString().appendText(nls.localize('breakpointUnverifieddHover', "Unverified Breakpoint")),
stickiness
};
private static BREAKPOINT_DIRTY_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-unverified-glyph',
glyphMarginHoverMessage: new MarkdownString().appendText(nls.localize('breakpointDirtydHover', "Unverified breakpoint. File is modified, please restart debug session.")),
stickiness
};
private static BREAKPOINT_UNSUPPORTED_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-unsupported-glyph',
glyphMarginHoverMessage: new MarkdownString().appendText(nls.localize('breakpointUnsupported', "Conditional breakpoints not supported by this debug type")),
stickiness
};
// we need a separate decoration for glyph margin, since we do not want it on each line of a multi line statement.
private static TOP_STACK_FRAME_MARGIN: IModelDecorationOptions = {
glyphMarginClassName: 'debug-top-stack-frame-glyph',
stickiness
};
private static FOCUSED_STACK_FRAME_MARGIN: IModelDecorationOptions = {
glyphMarginClassName: 'debug-focused-stack-frame-glyph',
stickiness
};
private static TOP_STACK_FRAME_DECORATION: IModelDecorationOptions = {
isWholeLine: true,
inlineClassName: 'debug-remove-token-colors',
className: 'debug-top-stack-frame-line',
stickiness
};
private static TOP_STACK_FRAME_EXCEPTION_DECORATION: IModelDecorationOptions = {
isWholeLine: true,
inlineClassName: 'debug-remove-token-colors',
className: 'debug-top-stack-frame-exception-line',
stickiness
};
private static TOP_STACK_FRAME_INLINE_DECORATION: IModelDecorationOptions = {
beforeContentClassName: 'debug-top-stack-frame-column'
};
private static FOCUSED_STACK_FRAME_DECORATION: IModelDecorationOptions = {
isWholeLine: true,
inlineClassName: 'debug-remove-token-colors',
className: 'debug-focused-stack-frame-line',
stickiness
};
}

View File

@@ -0,0 +1,80 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import nls = require('vs/nls');
import Filters = require('vs/base/common/filters');
import { TPromise } from 'vs/base/common/winjs.base';
import Quickopen = require('vs/workbench/browser/quickopen');
import QuickOpen = require('vs/base/parts/quickopen/common/quickOpen');
import Model = require('vs/base/parts/quickopen/browser/quickOpenModel');
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IDebugService, ILaunch } from 'vs/workbench/parts/debug/common/debug';
import * as errors from 'vs/base/common/errors';
class DebugEntry extends Model.QuickOpenEntry {
constructor(private debugService: IDebugService, private launch: ILaunch, private configurationName: string, highlights: Model.IHighlight[] = []) {
super(highlights);
}
public getLabel(): string {
return this.debugService.getConfigurationManager().getLaunches().length <= 1 ? this.configurationName : `${this.configurationName} (${this.launch.name})`;
}
public getAriaLabel(): string {
return nls.localize('entryAriaLabel', "{0}, debug", this.getLabel());
}
public run(mode: QuickOpen.Mode, context: Model.IContext): boolean {
if (mode === QuickOpen.Mode.PREVIEW) {
return false;
}
// Run selected debug configuration
this.debugService.getConfigurationManager().selectConfiguration(this.launch, this.configurationName);
this.debugService.startDebugging(this.launch.workspaceUri).done(undefined, errors.onUnexpectedError);
return true;
}
}
export class DebugQuickOpenHandler extends Quickopen.QuickOpenHandler {
constructor(
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IDebugService private debugService: IDebugService
) {
super();
}
public getAriaLabel(): string {
return nls.localize('debugAriaLabel', "Type a name of a launch configuration to run.");
}
public getResults(input: string): TPromise<Model.QuickOpenModel> {
const configurations: DebugEntry[] = [];
for (let launch of this.debugService.getConfigurationManager().getLaunches()) {
launch.getConfigurationNames().map(config => ({ config: config, highlights: Filters.matchesContiguousSubString(input, config) }))
.filter(({ highlights }) => !!highlights)
.forEach(({ config, highlights }) => configurations.push(new DebugEntry(this.debugService, launch, config, highlights)));
}
return TPromise.as(new Model.QuickOpenModel(configurations));
}
public getAutoFocus(input: string): QuickOpen.IAutoFocus {
return {
autoFocusFirstEntry: !!input
};
}
public getEmptyLabel(searchString: string): string {
if (searchString.length > 0) {
return nls.localize('noConfigurationsMatching', "No debug configurations matching");
}
return nls.localize('noConfigurationsFound', "No debug configurations found. Please create a 'launch.json' file.");
}
}

View File

@@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/debugViewlet';
import { Builder } from 'vs/base/browser/builder';
import * as DOM from 'vs/base/browser/dom';
import { TPromise } from 'vs/base/common/winjs.base';
import { IAction } from 'vs/base/common/actions';
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { PersistentViewsViewlet } from 'vs/workbench/parts/views/browser/views';
import { IDebugService, VIEWLET_ID, State } from 'vs/workbench/parts/debug/common/debug';
import { StartAction, ToggleReplAction, ConfigureAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { StartDebugActionItem } from 'vs/workbench/parts/debug/browser/debugActionItems';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
import { IProgressService, IProgressRunner } from 'vs/platform/progress/common/progress';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ViewLocation } from 'vs/workbench/parts/views/browser/viewsRegistry';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
export class DebugViewlet extends PersistentViewsViewlet {
private actions: IAction[];
private startDebugActionItem: StartDebugActionItem;
private progressRunner: IProgressRunner;
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IProgressService private progressService: IProgressService,
@IDebugService private debugService: IDebugService,
@IInstantiationService instantiationService: IInstantiationService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IStorageService storageService: IStorageService,
@IThemeService themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService,
@IContextMenuService contextMenuService: IContextMenuService,
@IExtensionService extensionService: IExtensionService
) {
super(VIEWLET_ID, ViewLocation.Debug, `${VIEWLET_ID}.state`, false, telemetryService, storageService, instantiationService, themeService, contextService, contextKeyService, contextMenuService, extensionService);
this.progressRunner = null;
this._register(this.debugService.onDidChangeState(state => this.onDebugServiceStateChange(state)));
}
public create(parent: Builder): TPromise<void> {
return super.create(parent).then(() => DOM.addClass(this.viewletContainer, 'debug-viewlet'));
}
public focus(): void {
super.focus();
if (!this.contextService.hasWorkspace()) {
this.views[0].focusBody();
}
if (this.startDebugActionItem) {
this.startDebugActionItem.focus();
}
}
public getActions(): IAction[] {
if (!this.actions) {
this.actions = [];
this.actions.push(this.instantiationService.createInstance(StartAction, StartAction.ID, StartAction.LABEL));
if (this.contextService.hasWorkspace()) {
this.actions.push(this.instantiationService.createInstance(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL));
}
this.actions.push(this._register(this.instantiationService.createInstance(ToggleReplAction, ToggleReplAction.ID, ToggleReplAction.LABEL)));
}
return this.actions;
}
public getSecondaryActions(): IAction[] {
return [];
}
public getActionItem(action: IAction): IActionItem {
if (action.id === StartAction.ID && this.contextService.hasWorkspace()) {
this.startDebugActionItem = this.instantiationService.createInstance(StartDebugActionItem, null, action);
return this.startDebugActionItem;
}
return null;
}
private onDebugServiceStateChange(state: State): void {
if (this.progressRunner) {
this.progressRunner.done();
}
if (state === State.Initializing) {
this.progressRunner = this.progressService.show(true);
} else {
this.progressRunner = null;
}
}
}

View File

@@ -0,0 +1,102 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!../browser/media/exceptionWidget';
import * as nls from 'vs/nls';
import * as dom from 'vs/base/browser/dom';
import { ZoneWidget } from 'vs/editor/contrib/zoneWidget/browser/zoneWidget';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IDebugService, IExceptionInfo } from 'vs/workbench/parts/debug/common/debug';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { Color } from 'vs/base/common/color';
import { registerColor } from 'vs/platform/theme/common/colorRegistry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { LinkDetector } from 'vs/workbench/parts/debug/browser/linkDetector';
const $ = dom.$;
// theming
export const debugExceptionWidgetBorder = registerColor('debugExceptionWidget.border', { dark: '#a31515', light: '#a31515', hc: '#a31515' }, nls.localize('debugExceptionWidgetBorder', 'Exception widget border color.'));
export const debugExceptionWidgetBackground = registerColor('debugExceptionWidget.background', { dark: '#a3151540', light: '#a315150d', hc: '#a3151573' }, nls.localize('debugExceptionWidgetBackground', 'Exception widget background color.'));
export class ExceptionWidget extends ZoneWidget {
private _backgroundColor: Color;
constructor(editor: ICodeEditor, private exceptionInfo: IExceptionInfo, private lineNumber: number,
@IContextViewService private contextViewService: IContextViewService,
@IDebugService private debugService: IDebugService,
@IThemeService themeService: IThemeService,
@IInstantiationService private instantiationService: IInstantiationService
) {
super(editor, { showFrame: true, showArrow: true, frameWidth: 1, className: 'exception-widget-container' });
this._backgroundColor = Color.white;
this._applyTheme(themeService.getTheme());
this._disposables.push(themeService.onThemeChange(this._applyTheme.bind(this)));
this.create();
const onDidLayoutChangeScheduler = new RunOnceScheduler(() => this._doLayout(undefined, undefined), 50);
this._disposables.push(this.editor.onDidLayoutChange(() => onDidLayoutChangeScheduler.schedule()));
this._disposables.push(onDidLayoutChangeScheduler);
}
private _applyTheme(theme: ITheme): void {
this._backgroundColor = theme.getColor(debugExceptionWidgetBackground);
let frameColor = theme.getColor(debugExceptionWidgetBorder);
this.style({
arrowColor: frameColor,
frameColor: frameColor
}); // style() will trigger _applyStyles
}
protected _applyStyles(): void {
if (this.container) {
this.container.style.backgroundColor = this._backgroundColor.toString();
}
super._applyStyles();
}
protected _fillContainer(container: HTMLElement): void {
this.setCssClass('exception-widget');
// Set the font size and line height to the one from the editor configuration.
const fontInfo = this.editor.getConfiguration().fontInfo;
this.container.style.fontSize = `${fontInfo.fontSize}px`;
this.container.style.lineHeight = `${fontInfo.lineHeight}px`;
let title = $('.title');
title.textContent = this.exceptionInfo.id ? nls.localize('exceptionThrownWithId', 'Exception has occurred: {0}', this.exceptionInfo.id) : nls.localize('exceptionThrown', 'Exception has occurred.');
dom.append(container, title);
if (this.exceptionInfo.description) {
let description = $('.description');
description.textContent = this.exceptionInfo.description;
dom.append(container, description);
}
if (this.exceptionInfo.details && this.exceptionInfo.details.stackTrace) {
let stackTrace = $('.stack-trace');
const linkDetector = this.instantiationService.createInstance(LinkDetector);
const linkedStackTrace = linkDetector.handleLinks(this.exceptionInfo.details.stackTrace);
typeof linkedStackTrace === 'string' ? stackTrace.textContent = linkedStackTrace : stackTrace.appendChild(linkedStackTrace);
dom.append(container, stackTrace);
}
}
protected _doLayout(heightInPixel: number, widthInPixel: number): void {
// Reload the height with respect to the exception text content and relayout it to match the line count.
this.container.style.height = 'initial';
const lineHeight = this.editor.getConfiguration().lineHeight;
const arrowHeight = Math.round(lineHeight / 3);
const computedLinesNumber = Math.ceil((this.container.offsetHeight + arrowHeight) / lineHeight);
this._relayout(computedLinesNumber);
}
}

View File

@@ -0,0 +1,114 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import strings = require('vs/base/common/strings');
import uri from 'vs/base/common/uri';
import { isMacintosh } from 'vs/base/common/platform';
import * as errors from 'vs/base/common/errors';
import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import * as nls from 'vs/nls';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
export class LinkDetector {
private static FILE_LOCATION_PATTERNS: RegExp[] = [
// group 0: full path with line and column
// group 1: full path without line and column, matched by `*.*` in the end to work only on paths with extensions in the end (s.t. node:10352 would not match)
// group 2: drive letter on windows with trailing backslash or leading slash on mac/linux
// group 3: line number, matched by (:(\d+))
// group 4: column number, matched by ((?::(\d+))?)
// eg: at Context.<anonymous> (c:\Users\someone\Desktop\mocha-runner\test\test.js:26:11)
/(?![\(])(?:file:\/\/)?((?:([a-zA-Z]+:)|[^\(\)<>\'\"\[\]:\s]+)(?:[\\/][^\(\)<>\'\"\[\]:]*)?\.[a-zA-Z]+[0-9]*):(\d+)(?::(\d+))?/g
];
constructor(
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IWorkspaceContextService private contextService: IWorkspaceContextService
) {
// noop
}
/**
* Matches and handles relative and absolute file links in the string provided.
* Returns <span/> element that wraps the processed string, where matched links are replaced by <a/> and unmatched parts are surrounded by <span/> elements.
* 'onclick' event is attached to all anchored links that opens them in the editor.
* If no links were detected, returns the original string.
*/
public handleLinks(text: string): HTMLElement | string {
let linkContainer: HTMLElement;
for (let pattern of LinkDetector.FILE_LOCATION_PATTERNS) {
pattern.lastIndex = 0; // the holy grail of software development
let lastMatchIndex = 0;
let match = pattern.exec(text);
while (match !== null) {
let resource: uri = null;
try {
resource = (match && !strings.startsWith(match[0], 'http'))
&& (match[2] || strings.startsWith(match[1], '/') ? uri.file(match[1]) : this.contextService.toResource(match[1])); // TODO@Michel TODO@Isidor (https://github.com/Microsoft/vscode/issues/29190)
} catch (e) { }
if (!resource) {
match = pattern.exec(text);
continue;
}
if (!linkContainer) {
linkContainer = document.createElement('span');
}
let textBeforeLink = text.substring(lastMatchIndex, match.index);
if (textBeforeLink) {
let span = document.createElement('span');
span.textContent = textBeforeLink;
linkContainer.appendChild(span);
}
const link = document.createElement('a');
link.textContent = text.substr(match.index, match[0].length);
link.title = isMacintosh ? nls.localize('fileLinkMac', "Click to follow (Cmd + click opens to the side)") : nls.localize('fileLink', "Click to follow (Ctrl + click opens to the side)");
linkContainer.appendChild(link);
const line = Number(match[3]);
const column = match[4] ? Number(match[4]) : undefined;
link.onclick = (e) => this.onLinkClick(new StandardMouseEvent(e), resource, line, column);
lastMatchIndex = pattern.lastIndex;
const currentMatch = match;
match = pattern.exec(text);
// Append last string part if no more link matches
if (!match) {
let textAfterLink = text.substr(currentMatch.index + currentMatch[0].length);
if (textAfterLink) {
let span = document.createElement('span');
span.textContent = textAfterLink;
linkContainer.appendChild(span);
}
}
}
}
return linkContainer || text;
}
private onLinkClick(event: IMouseEvent, resource: uri, line: number, column: number = 0): void {
const selection = window.getSelection();
if (selection.type === 'Range') {
return; // do not navigate when user is selecting
}
event.preventDefault();
this.editorService.openEditor({
resource,
options: {
selection: {
startLineNumber: line,
startColumn: column
}
}
}, event.ctrlKey || event.metaKey).done(null, errors.onUnexpectedError);
}
}

View File

@@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><title>Layer 1</title><rect height="11" width="3" y="3" x="7" fill="#fff"/><rect height="3" width="11" y="7" x="3" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 197 B

View File

@@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><title>Layer 1</title><rect height="11" width="3" y="3" x="7" fill="#C5C5C5"/><rect height="3" width="11" y="7" x="3" fill="#C5C5C5"/></svg>

After

Width:  |  Height:  |  Size: 203 B

View File

@@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><title>Layer 1</title><rect height="11" width="3" y="3" x="7" fill="#424242"/><rect height="3" width="11" y="7" x="3" fill="#424242"/></svg>

After

Width:  |  Height:  |  Size: 203 B

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#CC1100;}
</style>
<path class="st0" d="M8,3C5.2,3,3,5.2,3,8s2.2,5,5,5s5-2.2,5-5S10.8,3,8,3z M10.8,9.9H5.2V8.7h5.7V9.9z M10.8,7.3H5.2V6.1h5.7V7.3z"
/>
</svg>

After

Width:  |  Height:  |  Size: 539 B

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#E51400;}
</style>
<path class="st0" d="M8,3C5.2,3,3,5.2,3,8s2.2,5,5,5s5-2.2,5-5S10.8,3,8,3z M10.8,9.9H5.2V8.7h5.7V9.9z M10.8,7.3H5.2V6.1h5.7V7.3z"
/>
</svg>

After

Width:  |  Height:  |  Size: 539 B

View File

@@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g fill="#c10"><circle cx="8" cy="8" r="5"/></g></g></svg>

After

Width:  |  Height:  |  Size: 176 B

View File

@@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" fill-opacity="0.8"><g fill="#5A5A5A"><circle cx="8" cy="8" r="5"/></g></g></svg>

After

Width:  |  Height:  |  Size: 198 B

View File

@@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" fill-opacity="0.6"><g fill="#6C6C6C"><circle cx="8" cy="8" r="5"/></g></g></svg>

After

Width:  |  Height:  |  Size: 198 B

View File

@@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" fill-opacity="0.4"><g fill="#E51400"><circle cx="8" cy="8" r="5"/></g></g></svg>

After

Width:  |  Height:  |  Size: 198 B

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#CC1100;}
.st1{fill:#FFFFFF;}
</style>
<g>
<g>
<circle class="st0" cx="8" cy="8" r="5"/>
</g>
</g>
<g>
<rect x="7.3" y="10.2" class="st1" width="1.5" height="1.5"/>
<rect x="7.3" y="4.4" class="st1" width="1.5" height="4.4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 530 B

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#E51400;}
.st1{fill:#FFFFFF;}
</style>
<g>
<g>
<circle class="st0" cx="8" cy="8" r="5"/>
</g>
</g>
<g>
<rect x="7.3" y="10.2" class="st1" width="1.5" height="1.5"/>
<rect x="7.3" y="4.4" class="st1" width="1.5" height="4.4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 530 B

View File

@@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g stroke="#5A5A5A" stroke-width="3" stroke-opacity="0.8"><circle cx="8" cy="8" r="4"/></g></g></svg>

After

Width:  |  Height:  |  Size: 219 B

View File

@@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g stroke="#6C6C6C" stroke-width="3" stroke-opacity="0.6"><circle cx="8" cy="8" r="4"/></g></g></svg>

After

Width:  |  Height:  |  Size: 219 B

View File

@@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g fill="#E51400"><circle cx="8" cy="8" r="5"/></g></g></svg>

After

Width:  |  Height:  |  Size: 179 B

View File

@@ -0,0 +1,41 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-editor .zone-widget .zone-widget-container.breakpoint-widget {
height: 30px !important;
display: flex;
border-color: #007ACC;
}
.monaco-editor .zone-widget .zone-widget-container.breakpoint-widget .breakpoint-select-container {
display: flex;
justify-content: center;
flex-direction: column;
padding: 0 10px;
}
.monaco-editor .zone-widget .zone-widget-container.breakpoint-widget .inputBoxContainer {
flex: 1;
}
.monaco-editor .zone-widget .zone-widget-container.breakpoint-widget .monaco-inputbox {
border: none;
}
.monaco-editor .breakpoint-widget .input {
font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback";
line-height: 22px;
background-color: transparent;
padding: 8px;
}
.monaco-workbench.mac .monaco-editor .breakpoint-widget .input {
font-size: 11px;
}
.monaco-workbench.windows .monaco-editor .breakpoint-widget .input,
.monaco-workbench.linux .monaco-editor .breakpoint-widget .input {
font-size: 13px;
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#1E1E1E" d="M16 5.5c0-3-2.5-5.5-5.5-5.5C7.6 0 5.3 2.2 5 5c-2.8.2-5 2.6-5 5.5 0 3 2.5 5.5 5.5 5.5 2.9 0 5.2-2.2 5.5-5 2.8-.3 5-2.6 5-5.5z"/><g fill="#C5C5C5"><path d="M10.5 1C8.2 1 6.3 2.8 6 5c.3 0 .7.1 1 .2C7.2 3.4 8.7 2 10.5 2 12.4 2 14 3.6 14 5.5c0 1.8-1.4 3.3-3.2 3.5.1.3.2.6.2 1 2.3-.2 4-2.1 4-4.5C15 3 13 1 10.5 1z"/><circle cx="5.5" cy="10.5" r="4.5"/></g></svg>

After

Width:  |  Height:  |  Size: 497 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#F6F6F6" d="M16 5.5c0-3-2.5-5.5-5.5-5.5C7.6 0 5.3 2.2 5 5c-2.8.2-5 2.6-5 5.5 0 3 2.5 5.5 5.5 5.5 2.9 0 5.2-2.2 5.5-5 2.8-.3 5-2.6 5-5.5z"/><g fill="#424242"><path d="M10.5 1C8.2 1 6.3 2.8 6 5c.3 0 .7.1 1 .2C7.2 3.4 8.7 2 10.5 2 12.4 2 14 3.6 14 5.5c0 1.8-1.4 3.3-3.2 3.5.1.3.2.6.2 1 2.3-.2 4-2.1 4-4.5C15 3 13 1 10.5 1z"/><circle cx="5.5" cy="10.5" r="4.5"/></g></svg>

After

Width:  |  Height:  |  Size: 497 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#1E1E1E" d="M4.222 0h-2.222v.479c-.526.648-.557 1.57-.043 2.269l.043.059v3.203l-.4.296-.053.053c-.353.352-.547.822-.547 1.321s.194.967.549 1.32c.134.134.288.236.451.322v6.678h14v-16h-11.778z"/><path fill="#E8E8E8" d="M10.798 7l-1.83-2h6.032v2h-4.202zm-2.292-6h-3.207l1.337 1.52 1.87-1.52zm-5.506 8.531v1.469h12v-2h-10.813l-.024.021c-.3.299-.716.479-1.163.51zm0 5.469h12v-2h-12v2zm3.323-8h.631l-.347-.266-.284.266zm8.677-4v-2h-3.289l-1.743 2h5.032z"/><path fill="#F48771" d="M7.246 4.6l2.856-3.277-.405-.002-3.176 2.581-2.607-2.962c-.336-.221-.786-.2-1.082.096-.308.306-.319.779-.069 1.12l2.83 2.444-3.339 2.466c-.339.338-.339.887 0 1.225.339.337.888.337 1.226 0l3.063-2.867 3.33 2.555h.466l-3.093-3.379z"/></svg>

After

Width:  |  Height:  |  Size: 787 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#fff" d="M4.222 0h-2.222v.479c-.526.648-.557 1.57-.043 2.269l.043.059v3.203l-.4.296-.053.053c-.353.352-.547.822-.547 1.321s.194.967.549 1.32c.134.134.288.236.451.322v6.678h14v-16h-11.778z"/><path fill="#424242" d="M10.798 7l-1.83-2h6.032v2h-4.202zm-2.292-6h-3.207l1.337 1.52 1.87-1.52zm-5.506 8.531v1.469h12v-2h-10.813l-.024.021c-.3.299-.716.479-1.163.51zm0 5.469h12v-2h-12v2zm3.323-8h.631l-.347-.266-.284.266zm8.677-4v-2h-3.289l-1.743 2h5.032z"/><path fill="#A1260D" d="M7.246 4.6l2.856-3.277-.405-.002-3.176 2.581-2.607-2.962c-.336-.221-.786-.2-1.082.096-.308.306-.319.779-.069 1.12l2.83 2.444-3.339 2.466c-.339.338-.339.887 0 1.225.339.337.888.337 1.226 0l3.063-2.867 3.33 2.555h.466l-3.093-3.379z"/></svg>

After

Width:  |  Height:  |  Size: 784 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#C5C5C5"><path d="M12.714 9.603c-.07.207-.15.407-.246.601l1.017 2.139c-.335.424-.718.807-1.142 1.143l-2.14-1.018c-.193.097-.394.176-.601.247l-.795 2.235c-.265.03-.534.05-.807.05-.272 0-.541-.02-.806-.05l-.795-2.235c-.207-.071-.408-.15-.602-.247l-2.14 1.017c-.424-.336-.807-.719-1.143-1.143l1.017-2.139c-.094-.193-.175-.393-.245-.6l-2.236-.796c-.03-.265-.05-.534-.05-.807s.02-.542.05-.807l2.236-.795c.07-.207.15-.407.246-.601l-1.016-2.139c.336-.423.719-.807 1.143-1.142l2.14 1.017c.193-.096.394-.176.602-.247l.793-2.236c.265-.03.534-.05.806-.05.273 0 .542.02.808.05l.795 2.236c.207.07.407.15.601.246l2.14-1.017c.424.335.807.719 1.142 1.142l-1.017 2.139c.096.194.176.394.246.601l2.236.795c.029.266.049.535.049.808s-.02.542-.05.807l-2.236.796zm-4.714-4.603c-1.657 0-3 1.343-3 3s1.343 3 3 3 3-1.343 3-3-1.343-3-3-3z"/><circle cx="8" cy="8" r="1.5"/></g></svg>

After

Width:  |  Height:  |  Size: 927 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#424242"><path d="M12.714 9.603c-.07.207-.15.407-.246.601l1.017 2.139c-.335.424-.718.807-1.142 1.143l-2.14-1.018c-.193.097-.394.176-.601.247l-.795 2.235c-.265.03-.534.05-.807.05-.272 0-.541-.02-.806-.05l-.795-2.235c-.207-.071-.408-.15-.602-.247l-2.14 1.017c-.424-.336-.807-.719-1.143-1.143l1.017-2.139c-.094-.193-.175-.393-.245-.6l-2.236-.796c-.03-.265-.05-.534-.05-.807s.02-.542.05-.807l2.236-.795c.07-.207.15-.407.246-.601l-1.016-2.139c.336-.423.719-.807 1.143-1.142l2.14 1.017c.193-.096.394-.176.602-.247l.793-2.236c.265-.03.534-.05.806-.05.273 0 .542.02.808.05l.795 2.236c.207.07.407.15.601.246l2.14-1.017c.424.335.807.719 1.142 1.142l-1.017 2.139c.096.194.176.394.246.601l2.236.795c.029.266.049.535.049.808s-.02.542-.05.807l-2.236.796zm-4.714-4.603c-1.657 0-3 1.343-3 3s1.343 3 3 3 3-1.343 3-3-1.343-3-3-3z"/><circle cx="8" cy="8" r="1.5"/></g></svg>

After

Width:  |  Height:  |  Size: 927 B

View File

@@ -0,0 +1,3 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-3 0 16 16" enable-background="new -3 0 16 16"><path fill="#89D185" d="M1 2v12l8-6-8-6z"/></svg>

After

Width:  |  Height:  |  Size: 323 B

View File

@@ -0,0 +1,3 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-3 0 16 16" enable-background="new -3 0 16 16"><path fill="#388A34" d="M1 2v12l8-6-8-6z"/></svg>

After

Width:  |  Height:  |  Size: 323 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-red{fill:#e51400}.icon-vs-yellow{fill:#fc0}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-bg" d="M14.414 8l-5 6H3V2h6.414l5 6z" id="outline" style="display: none;"/><path class="icon-vs-yellow" d="M13 8l-4 5H4V3h5l4 5z" id="iconBg"/><g id="iconFg"><path class="icon-vs-red" d="M10.5 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/></g></svg>

After

Width:  |  Height:  |  Size: 530 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-yellow{fill:#fc0}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-bg" d="M14.414 8l-5 6H3V2h6.414l5 6z" id="outline" style="display: none;"/><g id="iconBg"><path class="icon-vs-yellow" d="M13 8l-4 5H4V3h5l4 5z"/></g></svg>

After

Width:  |  Height:  |  Size: 424 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M17 19.488v4.248c0 .462.09 1.264-.373 1.264H15v-1h1v-3.19l-.173-.18c-1.453 1.205-3.528 1.248-4.67.108C10 19.578 10.118 18 11.376 16H8v1H7v-1.627C7 14.91 7.802 15 8.264 15h4.105L17 19.488zM14 9h-1V8h1.955c.46 0 1.045.22 1.045.682v3.345l.736.875c.18-.973.89-1.71 1.914-1.71.143 0 .35.014.35.04V9h1v2.618c0 .117.265.382.382.382H23v1h-2.233c.027 0 .042.154.042.298 0 1.025-.74 1.753-1.712 1.932l.875.77H23.318c.462 0 .682.583.682 1.045V19h-1v-1h-2.52L14 11.698V9zM16 4C9.373 4 4 9.373 4 16s5.373 12 12 12 12-5.373 12-12S22.627 4 16 4zm10 12c0 2.397-.85 4.6-2.262 6.324L9.676 8.262C11.4 6.85 13.602 6 16 6c5.514 0 10 4.486 10 10zM6 16c0-2.398.85-4.6 2.262-6.324L22.324 23.74C20.6 25.15 18.397 26 16 26c-5.514 0-10-4.486-10-10z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 834 B

View File

@@ -0,0 +1,263 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* Activity Bar */
.monaco-workbench > .activitybar .monaco-action-bar .action-label.debug {
-webkit-mask: url('debug-dark.svg') no-repeat 50% 50%;
}
.monaco-editor .debug-top-stack-frame-line,
.monaco-editor .debug-top-stack-frame-exception-line {
background: rgba(255, 255, 102, 0.45);
}
.monaco-editor .debug-top-stack-frame-range {
background: #ffeca0;
}
.monaco-editor .debug-top-stack-frame-column::before {
background: url('current-arrow.svg') center center no-repeat;
}
.monaco-editor .debug-focused-stack-frame-line {
background: rgba(206, 231, 206, 0.45);
}
.monaco-editor .debug-focused-stack-frame-range {
background: rgba(206, 231, 206, 1);
}
.monaco-editor .debug-breakpoint-hint-glyph {
background: url('breakpoint-hint.svg') center center no-repeat;
}
.monaco-editor .debug-breakpoint-disabled-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-disabled-glyph-column::before {
background: url('breakpoint-disabled.svg') center center no-repeat;
}
.monaco-editor .debug-breakpoint-unverified-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-unverified-glyph-column::before {
background: url('breakpoint-unverified.svg') center center no-repeat;
}
.monaco-editor .debug-top-stack-frame-glyph {
background: url('current-arrow.svg') center center no-repeat;
}
.monaco-editor .debug-focused-stack-frame-glyph {
background: url('stackframe-arrow.svg') center center no-repeat;
}
.monaco-editor .debug-breakpoint-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-glyph-column::before {
background: url('breakpoint.svg') center center no-repeat;
}
.monaco-editor .debug-breakpoint-column::before,
.monaco-editor .debug-top-stack-frame-column::before {
content: " ";
width: 0.9em;
height: 0.8em;
display: inline-block;
margin-right: 2px;
margin-left: 2px;
background-size: 110% !important;
background-position: initial !important;
}
.monaco-editor .debug-breakpoint-conditional-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-conditional-glyph-column::before {
background: url('breakpoint-conditional.svg') center center no-repeat;
}
.monaco-editor .debug-breakpoint-unsupported-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-unsupported-glyph-column::before {
background: url('breakpoint-unsupported.svg') center center no-repeat;
}
.monaco-editor .debug-top-stack-frame-glyph.debug-breakpoint-glyph,
.monaco-editor .debug-top-stack-frame-glyph.debug-breakpoint-conditional-glyph,
.monaco-editor .debug-breakpoint-column.debug-breakpoint-glyph-column.debug-top-stack-frame-column::before,
.monaco-editor.vs-dark .debug-top-stack-frame-glyph.debug-breakpoint-glyph,
.monaco-editor.vs-dark .debug-top-stack-frame-glyph.debug-breakpoint-conditional-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-glyph-column.debug-top-stack-frame-column::before {
background: url('current-and-breakpoint.svg') center center no-repeat;
}
.monaco-editor .debug-focused-stack-frame-glyph.debug-breakpoint-glyph,
.monaco-editor .debug-focused-stack-frame-glyph.debug-breakpoint-conditional-glyph {
background: url('stackframe-and-breakpoint.svg') center center no-repeat;
}
/* Error editor */
.debug-error-editor:focus {
outline: none !important;
}
.debug-error-editor {
padding: 5px 0 0 10px;
box-sizing: border-box;
}
/* Expressions */
.monaco-workbench .monaco-tree-row .expression {
overflow: hidden;
text-overflow: ellipsis;
font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback";
}
.monaco-workbench.mac .monaco-tree-row .expression {
font-size: 11px;
}
.monaco-workbench.windows .monaco-tree-row .expression,
.monaco-workbench.linux .monaco-tree-row .expression {
font-size: 13px;
}
.monaco-workbench .monaco-tree-row .expression .value {
margin-left: 6px;
}
.monaco-workbench .monaco-tree-row:not(.selected) .expression .name {
color: #9B46B0;
}
.monaco-workbench > .monaco-tree-row:not(.selected) .expression .value {
color: rgba(108, 108, 108, 0.8);
}
.monaco-workbench .monaco-tree-row .expression .unavailable {
font-style: italic;
}
.monaco-workbench .monaco-tree-row:not(.selected) .expression .error {
color: #E51400;
}
.monaco-workbench .monaco-tree-row:not(.selected) .expression .value.number {
color: #09885A;
}
.monaco-workbench .monaco-tree-row:not(.selected) .expression .value.boolean {
color: #0000FF;
}
.monaco-workbench .monaco-tree-row:not(.selected) .expression .value.string {
color: #A31515;
}
.vs-dark .monaco-workbench > .monaco-tree-row:not(.selected) .expression .value {
color: rgba(204, 204, 204, 0.6);
}
.vs-dark .monaco-workbench .monaco-tree-row:not(.selected) .expression .error {
color: #F48771;
}
.vs-dark .monaco-workbench .monaco-tree-row:not(.selected) .expression .value.number {
color: #B5CEA8;
}
.hc-black .monaco-workbench .monaco-tree-row:not(.selected) .expression .value.number {
color: #89d185;
}
.hc-black .monaco-workbench .monaco-tree-row:not(.selected) .expression .value.boolean {
color: #75bdfe;
}
.hc-black .monaco-workbench .monaco-tree-row:not(.selected) .expression .value.string {
color: #f48771;
}
.vs-dark .monaco-workbench .monaco-tree-row:not(.selected) .expression .value.boolean {
color: #4E94CE;
}
.vs-dark .monaco-workbench .monaco-tree-row:not(.selected) .expression .value.string {
color: #CE9178;
}
.hc-black .monaco-workbench .monaco-tree-row:not(.selected) .expression .error {
color: #F48771;
}
/* Dark theme */
.vs-dark .monaco-workbench .monaco-tree-row:not(.selected) .expression .name {
color: #C586C0;
}
.monaco-editor.vs-dark .debug-focused-stack-frame-line {
background: rgba(122, 189, 122, 0.3);
}
.monaco-editor.vs-dark .debug-focused-stack-frame-range {
background: rgba(122, 189, 122, 0.5);
}
.monaco-editor.vs-dark .debug-top-stack-frame-line,
.monaco-editor.vs-dark .debug-top-stack-frame-exception-line {
background-color: rgba(255, 255, 0, 0.2)
}
.monaco-editor.vs-dark .debug-top-stack-frame-range {
background-color: rgba(255, 255, 0, 0.3)
}
.monaco-editor.vs-dark .debug-breakpoint-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-glyph-column::before {
background: url('breakpoint-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-breakpoint-conditional-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-conditional-glyph-column::before {
background: url('breakpoint-conditional-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-breakpoint-unsupported-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-unsupported-glyph-column::before {
background: url('breakpoint-unsupported-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-breakpoint-disabled-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-disabled-glyph-column::before {
background: url('breakpoint-disabled-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-breakpoint-unverified-glyph,
.monaco-editor.vs-dark .debug-breakpoint-column.debug-breakpoint-unverified-glyph-column::before {
background: url('breakpoint-unverified-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-focused-stack-frame-glyph {
background: url('stackframe-arrow-dark.svg') center center no-repeat;
}
.monaco-editor.vs-dark .debug-focused-stack-frame-glyph.debug-breakpoint-glyph,
.monaco-editor.vs-dark .debug-focused-stack-frame-glyph.debug-breakpoint-conditional-glyph {
background: url('stackframe-and-breakpoint-dark.svg') center center no-repeat;
}
/* High Contrast Theming */
.monaco-editor.hc-black .debug-focused-stack-frame-line {
background: rgba(206, 231, 206, 1);
}
.hc-black .monaco-workbench .monaco-tree-row:not(.selected) .expression .name {
color: inherit;
}
.hc-black .monaco-editor .debug-top-stack-frame-line {
background: rgba(255, 246, 0, 1);
}
.hc-black .monaco-editor .debug-remove-token-colors {
color:black;
}

View File

@@ -0,0 +1,129 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* Debug actions widget */
.monaco-workbench .debug-actions-widget {
position: absolute;
z-index: 200;
height: 32px;
display: flex;
padding-left: 7px;
}
.monaco-workbench .debug-actions-widget .monaco-action-bar .action-item.select-container {
margin-right: 7px;
}
.monaco-workbench .debug-actions-widget .monaco-action-bar .action-item .select-box {
margin-top: 6px;
}
.monaco-workbench .debug-actions-widget .drag-area {
cursor: -webkit-grab;
height: 32px;
width: 10px;
background: url('drag.svg') center center no-repeat;
}
.monaco-workbench .debug-actions-widget .drag-area.dragged {
cursor: -webkit-grabbing;
}
.monaco-workbench .debug-actions-widget .monaco-action-bar .action-item > .action-label {
width: 32px;
height: 32px;
margin-right: 0;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
}
/* Debug actionbar actions */
.monaco-workbench .debug-actions-widget .debug-action.step-over,
.monaco-workbench .debug-actions-widget .debug-action.step-back {
background-image: url('step-over.svg');
}
.monaco-workbench .debug-actions-widget .debug-action.step-into {
background-image: url('step-into.svg');
}
.monaco-workbench .debug-actions-widget .debug-action.step-out {
background-image: url('step-out.svg');
}
.monaco-workbench .debug-actions-widget .debug-action.step-back,
.monaco-workbench .debug-actions-widget .debug-action.reverse-continue {
transform: scaleX(-1);
}
.monaco-workbench .debug-actions-widget .debug-action.continue,
.monaco-workbench .debug-actions-widget .debug-action.reverse-continue {
background-image: url('continue.svg');
}
.monaco-workbench .debug-actions-widget .debug-action.restart {
background-image: url('restart.svg');
}
.monaco-workbench .debug-actions-widget .debug-action.pause {
background-image: url('pause.svg');
}
.monaco-workbench .debug-actions-widget .debug-action.stop {
background-image: url('stop.svg');
}
.monaco-workbench .debug-actions-widget .debug-action.disconnect {
background-image: url('disconnect.svg');
}
/* Dark and hc theme actions */
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.step-over,
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.step-back,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.step-over,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.step-back {
background-image: url('step-over-inverse.svg');
}
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.step-into,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.step-into {
background-image: url('step-into-inverse.svg');
}
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.step-out,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.step-out {
background-image: url('step-out-inverse.svg');
}
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.continue,
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.reverse-continue,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.continue,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.reverse-continue {
background-image: url('continue-inverse.svg');
}
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.restart,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.restart {
background-image: url('restart-inverse.svg');
}
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.pause,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.pause {
background-image: url('pause-inverse.svg');
}
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.stop,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.stop {
background-image: url('stop-inverse.svg');
}
.vs-dark .monaco-workbench .debug-actions-widget .debug-action.disconnect,
.hc-black .monaco-workbench .debug-actions-widget .debug-action.disconnect {
background-image: url('disconnect-inverse.svg');
}

View File

@@ -0,0 +1,117 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-editor .debug-hover-widget {
position: absolute;
margin-top: -1px;
cursor: default;
z-index: 50;
animation-duration: 0.15s;
animation-name: fadeIn;
-webkit-user-select: text;
word-break: break-all;
padding: 4px 5px;
}
.monaco-editor .debug-hover-widget .complex-value {
width: 324px;
}
.monaco-editor .debug-hover-widget .complex-value .title {
padding-left: 15px;
padding-right: 2px;
font-size: 11px;
word-break: normal;
text-overflow: ellipsis;
height: 18px;
overflow: hidden;
border-bottom: 1px solid rgba(128, 128, 128, 0.35);
}
.monaco-editor .debug-hover-widget .debug-hover-tree {
line-height: 18px;
}
.monaco-editor .debug-hover-widget .debug-hover-tree .monaco-tree .monaco-tree-row > .content {
-webkit-user-select: text;
white-space: pre;
}
/* Disable tree highlight in debug hover tree. */
.monaco-editor .debug-hover-widget .debug-hover-tree .monaco-tree .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) {
background-color: inherit;
}
.monaco-editor .debug-hover-widget .debug-hover-tree .monaco-tree .monaco-tree-rows > .monaco-tree-row {
cursor: default;
}
.monaco-editor .debug-hover-widget .debug-hover-tree .monaco-tree .monaco-tree-rows > .monaco-tree-row.has-children {
cursor: pointer;
}
.monaco-editor .debug-hover-widget pre {
margin-top: 0;
margin-bottom: 0;
}
.monaco-editor .debugHoverHighlight {
background-color: rgba(173, 214, 255, 0.15);
}
.monaco-editor .debug-hover-widget .value {
white-space: pre-wrap;
color: rgba(108, 108, 108, 0.8);
overflow: auto;
max-height: 500px;
}
.monaco-editor .debug-hover-widget .error {
color: #E51400;
}
.monaco-editor .debug-hover-widget .value.number {
color: #09885A;
}
.monaco-editor .debug-hover-widget .value.boolean {
color: #0000FF;
}
.monaco-editor .debug-hover-widget .value.string {
color: #A31515;
}
/* Dark theme */
.monaco-editor.vs-dark .debug-hover-widget .value,
.monaco-editor.hc-black .debug-hover-widget .value {
color: rgba(204, 204, 204, 0.6);
}
.monaco-editor.vs-dark .debug-hover-widget .error,
.monaco-editor.hc-black .debug-hover-widget .error {
color: #F48771;
}
.monaco-editor.vs-dark .debug-hover-widget .value.number,
.monaco-editor.hc-black .debug-hover-widget .value.number {
color: #B5CEA8;
}
.monaco-editor.vs-dark .debug-hover-widget .value.boolean,
.monaco-editor.hc-black .debug-hover-widget .value.boolean {
color: #4E94CE;
}
.monaco-editor.vs-dark .debug-hover-widget .value.string,
.monaco-editor.hc-black .debug-hover-widget .value.string {
color: #CE9178;
}
.monaco-editor.vs-dark .debugHoverHighlight,
.monaco-editor.hc-theme .debugHoverHighlight {
background-color: rgba(38, 79, 120, 0.25);
}

View File

@@ -0,0 +1,396 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* Debug viewlet */
.debug-viewlet {
height: 100%;
}
/* Actionbar actions */
.monaco-workbench .debug-action.configure {
background: url('configure.svg') center center no-repeat;
}
.monaco-workbench .debug-action.start {
background: url('continue.svg') center center no-repeat;
}
.monaco-workbench .debug-action.toggle-repl {
background: url('repl.svg') center center no-repeat;
}
.monaco-workbench .debug-action.notification:before {
content: '';
width: 6px;
height: 6px;
background-color: #CC6633;
position: absolute;
top: 11px;
right: 5px;
border-radius: 10px;
border: 1px solid white;
}
.vs-dark .monaco-workbench .debug-action.start,
.hc-black .monaco-workbench .debug-action.start {
background: url('continue-inverse.svg') center center no-repeat;
}
.vs-dark .monaco-workbench .debug-action.configure,
.hc-black .monaco-workbench .debug-action.configure {
background: url('configure-inverse.svg') center center no-repeat;
}
.vs-dark .monaco-workbench .debug-action.toggle-repl,
.hc-black .monaco-workbench .debug-action.toggle-repl {
background: url('repl-inverse.svg') center center no-repeat;
}
.monaco-workbench > .part > .title > .title-actions .start-debug-action-item {
display: flex;
align-items: center;
font-size: 11px;
margin-right: 0.3em;
height: 20px;
flex-shrink: 1;
margin-top: 7px;
}
.monaco-workbench.mac > .part > .title > .title-actions .start-debug-action-item {
border-radius: 4px;
}
.monaco-workbench > .part > .title > .title-actions .start-debug-action-item .icon {
height: 20px;
width: 20px;
background: url('continue.svg') center center no-repeat;
flex-shrink: 0;
transition: transform 50ms ease;
-webkit-transition: -webkit-transform 50ms ease;
}
.vs-dark .monaco-workbench > .part > .title > .title-actions .start-debug-action-item .icon,
.hc-black .monaco-workbench > .part > .title > .title-actions .start-debug-action-item .icon {
background: url('continue-inverse.svg') center center no-repeat;
}
.monaco-workbench .monaco-action-bar .start-debug-action-item .configuration .select-box {
border: none;
margin-top: 0px;
cursor: pointer;
}
.monaco-workbench .monaco-action-bar .start-debug-action-item .configuration.disabled .select-box {
opacity: 0.7;
font-style: italic;
cursor: initial;
}
.monaco-workbench > .part > .title > .title-actions .start-debug-action-item .icon.active {
-webkit-transform: scale(1.272019649, 1.272019649);
transform: scale(1.272019649, 1.272019649);
}
/* Debug viewlet trees */
.debug-viewlet .monaco-tree .monaco-tree-row > .content {
line-height: 22px;
}
.debug-viewlet .line-number {
background: rgba(136, 136, 136, 0.3);
border-radius: 2px;
font-size: 0.9em;
padding: 0 3px;
margin-left: 0.8em;
}
.debug-viewlet .monaco-tree .monaco-tree-row.selected .line-number,
.debug-viewlet .monaco-tree .monaco-tree-row.selected .thread > .state > .label,
.debug-viewlet .monaco-tree .monaco-tree-row.selected .process > .state > .label {
background-color: #ffffff;
color: #666;
}
.debug-viewlet .monaco-tree .monaco-tree-row .content .monaco-action-bar {
visibility: hidden;
flex-shrink: 0;
}
.debug-viewlet .monaco-tree .monaco-tree-row .content .monaco-action-bar .action-label {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
.debug-viewlet .monaco-tree .monaco-tree-row:hover .content .monaco-action-bar,
.debug-viewlet .monaco-tree.focused .monaco-tree-row.focused .content .monaco-action-bar {
visibility: visible;
}
.debug-viewlet .disabled {
opacity: 0.35;
}
/* Call stack */
.debug-viewlet .debug-call-stack-title {
display: flex;
width: 100%;
}
.debug-viewlet .debug-call-stack-title > .pause-message {
flex: 1;
text-align: right;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
margin: 0px 10px;
}
.debug-viewlet .debug-call-stack-title > .pause-message > .label {
border-radius: 3px;
padding: 1px 2px;
font-size: 9px;
}
.debug-viewlet .debug-call-stack-title > .pause-message > .label.exception {
background-color: #A31515;
color: rgb(255, 255, 255);
}
.vs-dark .debug-viewlet .debug-call-stack-title > .pause-message > .label.exception {
background-color: #6C2022;
color: inherit;
}
.hc-black .debug-viewlet .debug-call-stack-title > .pause-message > .label.exception {
background-color: #6C2022;
color: inherit;
}
.debug-viewlet .debug-call-stack .thread,
.debug-viewlet .debug-call-stack .process {
display: flex;
}
.debug-viewlet .debug-call-stack .thread > .state,
.debug-viewlet .debug-call-stack .process > .state {
flex: 1;
text-align: right;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 10px;
text-transform: uppercase;
}
.debug-viewlet .debug-call-stack .thread > .state > .label,
.debug-viewlet .debug-call-stack .process > .state > .label {
background: rgba(136, 136, 136, 0.3);
border-radius: 2px;
font-size: 0.8em;
padding: 0 3px;
}
.debug-viewlet .debug-call-stack .stack-frame {
overflow: hidden;
text-overflow: ellipsis;
padding-right: 0.8em;
}
.debug-viewlet .debug-call-stack .stack-frame.label {
text-align: center;
font-style: italic;
}
.debug-viewlet .debug-call-stack .stack-frame.subtle {
font-style: italic;
}
.debug-viewlet .debug-call-stack .stack-frame.label > .file {
display: none;
}
.debug-viewlet .debug-call-stack .stack-frame > .file {
float: right;
}
.debug-viewlet .debug-call-stack .stack-frame > .file > .line-number.unavailable {
display: none;
}
.debug-viewlet .debug-call-stack > .monaco-tree-row:not(.selected) .stack-frame > .file {
color: rgba(108, 108, 108, 0.8);
}
.vs-dark .debug-viewlet .debug-call-stack > .monaco-tree-row:not(.selected) .stack-frame > .file {
color: rgba(204, 204, 204, 0.6);
}
.debug-viewlet .debug-call-stack .stack-frame > .file:not(:first-child) {
margin-left: 0.8em;
}
.debug-viewlet .debug-call-stack .load-more {
font-style: italic;
text-align: center;
}
.monaco-workbench .debug-viewlet .monaco-tree-row .expression {
white-space: pre;
}
.debug-viewlet .debug-call-stack .error {
font-style: italic;
text-overflow: ellipsis;
overflow: hidden;
}
/* Variables & Expression view */
.debug-viewlet .scope {
font-weight: bold;
font-size: 11px;
}
/* Animation of changed values in Debug viewlet */
@keyframes debugViewletValueChanged {
0% { background-color: rgba(86, 156, 214, 0) }
5% { background-color: rgba(86, 156, 214, .75) }
100% { background-color: rgba(86, 156, 214, .3) }
}
@keyframes debugViewletValueChangedDark {
0% { background-color: rgba(86, 156, 214, 0) }
5% { background-color: rgba(86, 156, 214, .5) }
100% { background-color: rgba(86, 156, 214, .2) }
}
.debug-viewlet .monaco-tree-row .expression .value.changed {
padding: 2px;
margin: 4px;
border-radius: 4px;
background-color: rgba(86, 156, 214, .5);
animation-name: debugViewletValueChanged;
animation-duration: .75s;
animation-fill-mode: forwards;
}
.debug-viewlet .monaco-inputbox {
width: 100%;
line-height: normal;
}
.debug-viewlet .inputBoxContainer {
box-sizing: border-box;
flex-grow: 1;
}
.debug-viewlet .debug-watch .monaco-inputbox {
font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback";
}
.debug-viewlet .monaco-inputbox > .wrapper {
height: 19px;
}
.debug-viewlet .monaco-inputbox > .wrapper > .input {
padding: 0px;
color: initial;
}
.debug-viewlet .watch-expression {
display: flex;
}
.debug-viewlet .watch-expression .expression {
flex : 1;
}
.debug-viewlet .debug-action.add-watch-expression,
.debug-viewlet .debug-action.add-function-breakpoint {
background: url('add.svg') center center no-repeat;
}
.debug-viewlet .focused .monaco-tree-row.selected:not(.highlighted) > .content.actions .debug-action.add-watch-expression {
background: url("add-focus.svg") center center no-repeat;
}
.vs-dark .debug-viewlet .debug-action.add-watch-expression,
.vs-dark .debug-viewlet .debug-action.add-function-breakpoint,
.hc-black .debug-viewlet .debug-action.add-watch-expression {
background: url('add-inverse.svg') center center no-repeat;
}
.vs-dark .debug-viewlet .monaco-tree-row .expression .value.changed {
animation-name: debugViewletValueChanged;
}
/* Breakpoints */
.debug-viewlet .debug-breakpoints .breakpoint {
display: flex;
padding-right: 0.8em;
flex: 1;
align-items: center;
}
.debug-viewlet .debug-breakpoints .breakpoint input {
flex-shrink: 0;
}
.debug-viewlet .debug-breakpoints .breakpoint > .file-path {
opacity: 0.7;
font-size: 0.9em;
margin-left: 0.8em;
flex: 1;
text-overflow: ellipsis;
overflow: hidden;
}
.debug-viewlet .debug-action.remove {
background: url('remove.svg') center center no-repeat;
}
.debug-viewlet .debug-action.remove-all {
background: url('remove-all.svg') center center no-repeat;
}
.debug-viewlet .debug-action.breakpoints-activate {
background: url('breakpoints-activate.svg') center center no-repeat;
}
.debug-viewlet .focused .monaco-tree-row.selected:not(.highlighted) > .content.actions .debug-action.remove,
.vs-dark .debug-viewlet .focused .monaco-tree-row.selected:not(.highlighted) > .content.actions .debug-action.remove {
background: url("remove-focus.svg") center center no-repeat;
}
.vs-dark .debug-viewlet .debug-action.remove,
.hc-black .debug-viewlet .debug-action.remove {
background: url('remove-inverse.svg') center center no-repeat;
}
.vs-dark .debug-viewlet .debug-action.remove-all,
.hc-black .debug-viewlet .debug-action.remove-all {
background: url('remove-all-inverse.svg') center center no-repeat;
}
.vs-dark .debug-viewlet .debug-action.breakpoints-activate,
.hc-black .debug-viewlet .debug-action.breakpoints-activate {
background: url('breakpoints-activate-inverse.svg') center center no-repeat;
}
/* No workspace view */
.debug-viewlet > .noworkspace-view {
padding: 0 20px 0 20px;
}
.debug-viewlet > .noworkspace-view > p {
line-height: 1.5em;
}

View File

@@ -0,0 +1 @@
<svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><style>.cls-1{fill:#f48771;}</style></defs><title>Plan de travail 1</title><path class="cls-1" d="M61.8,64H2.2A2.2,2.2,0,0,1,0,61.8V2.2A2.2,2.2,0,0,1,2.2,0H61.8A2.2,2.2,0,0,1,64,2.2V61.8A2.2,2.2,0,0,1,61.8,64ZM46,21.1H42V9.1h-5v12H26.9V9.1H22v12H18v4.1h1V42.4l9,7.3v7.7h8V49.7l9-7.3V25.2h1Z"/></svg>

After

Width:  |  Height:  |  Size: 423 B

View File

@@ -0,0 +1 @@
<svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><defs><style>.cls-1{fill:#ac4747;}</style></defs><title>Plan de travail 1</title><path class="cls-1" d="M61.8,64H2.2A2.2,2.2,0,0,1,0,61.8V2.2A2.2,2.2,0,0,1,2.2,0H61.8A2.2,2.2,0,0,1,64,2.2V61.8A2.2,2.2,0,0,1,61.8,64ZM46,21.1H42V9.1h-5v12H26.9V9.1H22v12H18v4.1h1V42.4l9,7.3v7.7h8V49.7l9-7.3V25.2h1Z"/></svg>

After

Width:  |  Height:  |  Size: 423 B

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="16px" height="32px" fill="#999">
<circle cx="5px" cy="11px" r="1.2"/>
<circle cx="10px" cy="11px" r="1.2"/>
<circle cx="5px" cy="16px" r="1.2"/>
<circle cx="10px" cy="16px" r="1.2"/>
<circle cx="5px" cy="21px" r="1.2"/>
<circle cx="10px" cy="21px" r="1.2"/>
</svg>

After

Width:  |  Height:  |  Size: 337 B

View File

@@ -0,0 +1,48 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-editor .zone-widget.exception-widget-container {
overflow: hidden;
}
.monaco-editor .zone-widget .zone-widget-container.exception-widget {
padding: 6px 10px;
white-space: pre-wrap;
-webkit-user-select: text;
-ms-user-select: text;
-khtml-user-select: text;
-moz-user-select: text;
-o-user-select: text;
user-select: text;
}
.monaco-editor .zone-widget .zone-widget-container.exception-widget .title {
font-weight: bold;
}
.monaco-editor .zone-widget .zone-widget-container.exception-widget .description,
.monaco-editor .zone-widget .zone-widget-container.exception-widget .stack-trace {
font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback";
}
.monaco-editor .zone-widget .zone-widget-container.exception-widget .stack-trace {
margin-top: 0.5em;
}
.monaco-editor .zone-widget .zone-widget-container.exception-widget a {
text-decoration: underline;
cursor: pointer;
}
/* High Contrast Theming */
.monaco-workbench.mac .zone-widget .zone-widget-container.exception-widget {
font-size: 11px;
}
.monaco-workbench.windows .zone-widget .zone-widget-container.exception-widget,
.monaco-workbench.linux .zone-widget .zone-widget-container.exception-widget {
font-size: 13px;
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path d="M13 13H3V2h10v11z" fill="#1E1E1E"/><path d="M7 12H4V3h3v9zm5-9H9v9h3V3z" fill="#75BEFF"/></svg>

After

Width:  |  Height:  |  Size: 221 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path d="M13 13H3V2h10v11z" fill="#F6F6F6"/><path d="M7 12H4V3h3v9zm5-9H9v9h3V3z" fill="#00539C"/></svg>

After

Width:  |  Height:  |  Size: 221 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#1E1E1E" d="M16 12h-2v2h-2v2H0V5h2V3h2V1h12v11z"/><g fill="#C5C5C5"><path d="M3 5h9v8h1V4H3zM5 2v1h9v8h1V2zM1 6v9h10V6H1zm8 7H7.5L6 11.5 4.5 13H3l2.3-2.3L3 8.5h1.5L6 10l1.5-1.5H9l-2.3 2.3L9 13z"/></g></svg>

After

Width:  |  Height:  |  Size: 335 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#F6F6F6" d="M16 12h-2v2h-2v2H0V5h2V3h2V1h12v11z"/><g fill="#424242"><path d="M3 5h9v8h1V4H3zM5 2v1h9v8h1V2zM1 6v9h10V6H1zm8 7H7.5L6 11.5 4.5 13H3l2.3-2.3L3 8.5h1.5L6 10l1.5-1.5H9l-2.3 2.3L9 13z"/></g></svg>

After

Width:  |  Height:  |  Size: 335 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="3 3 16 16" enable-background="new 3 3 16 16"><polygon fill="#FFF" points="12.597,11.042 15.4,13.845 13.844,15.4 11.042,12.598 8.239,15.4 6.683,13.845 9.485,11.042 6.683,8.239 8.238,6.683 11.042,9.486 13.845,6.683 15.4,8.239"/></svg>

After

Width:  |  Height:  |  Size: 304 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="3 3 16 16" enable-background="new 3 3 16 16"><polygon fill="#e8e8e8" points="12.597,11.042 15.4,13.845 13.844,15.4 11.042,12.598 8.239,15.4 6.683,13.845 9.485,11.042 6.683,8.239 8.238,6.683 11.042,9.486 13.845,6.683 15.4,8.239"/></svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="3 3 16 16" enable-background="new 3 3 16 16"><polygon fill="#424242" points="12.597,11.042 15.4,13.845 13.844,15.4 11.042,12.598 8.239,15.4 6.683,13.845 9.485,11.042 6.683,8.239 8.238,6.683 11.042,9.486 13.845,6.683 15.4,8.239"/></svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#252526;} .icon-vs-bg{fill:#c5c5c5;} .icon-vs-fg{fill:#2a292c;}</style><path class="icon-canvas-transparent" d="M32 32h-32v-32h32v32z" id="canvas"/><path class="icon-vs-out" d="M32 28h-32v-24h32v24z" id="outline"/><path class="icon-vs-bg" d="M2 6v20h28v-20h-28zm26 18h-24v-16h24v16zm-13-8l-5.25 5.5-1.75-1.833 3.5-3.667-3.5-3.667 1.75-1.833 5.25 5.5z" id="iconBg"/><g id="iconFg"><path class="icon-vs-fg" d="M4 8v16h24v-16h-24zm5.75 13.5l-1.75-1.833 3.5-3.667-3.5-3.667 1.75-1.833 5.25 5.5-5.25 5.5z"/></g></svg>

After

Width:  |  Height:  |  Size: 686 B

View File

@@ -0,0 +1,182 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/* Debug repl */
.monaco-workbench .repl {
height: 100%;
box-sizing: border-box;
overflow: hidden;
}
.monaco-workbench .repl .surveyor {
font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback";
position: absolute;
display: inline-block;
width : auto;
top: 0;
left: 0;
visibility: hidden;
}
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content {
line-height: 18px;
-webkit-user-select: text;
/* Wrap words but also do not trim whitespace #6275 */
word-wrap: break-word;
white-space: pre-wrap;
/* Break on all #7533 */
word-break: break-all;
}
.monaco-workbench.mac .repl .repl-tree .monaco-tree-row .input.expression,
.monaco-workbench.mac .repl .repl-tree .monaco-tree-row .output.expression {
font-size: 12px;
}
.monaco-workbench.windows .repl .repl-tree .monaco-tree-row .input.expression,
.monaco-workbench.windows .repl .repl-tree .monaco-tree-row .output.expression,
.monaco-workbench.linux .repl .repl-tree .monaco-tree-row .input.expression,
.monaco-workbench.linux .repl .repl-tree .monaco-tree-row .output.expression {
font-size: 14px;
}
.monaco-workbench .repl .repl-tree .monaco-tree-row .output.expression > .value {
margin-left: 0px;
}
.monaco-workbench .repl .repl-tree .monaco-tree-row .output.expression > .annotation {
font-size: inherit;
padding-left: 6px;
}
.monaco-workbench .repl .repl-tree .monaco-tree-row .output.expression .name:not(:empty) {
margin-right: 6px;
}
/* Allign twistie since repl tree is smaller and sometimes has paired elements */
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row.has-children > .content.input-output-pair:before {
top: 8px;
cursor: pointer;
}
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row.has-children > .content.input-output-pair:after {
top: 10px;
}
.monaco-workbench .repl .repl-input-wrapper {
padding-left: 20px;
border-top: 1px solid rgba(128, 128, 128, 0.35);
}
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-rows > .monaco-tree-row {
cursor: default;
}
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-rows > .monaco-tree-row.has-children .content .expression {
cursor: pointer;
}
/* Disable repl hover highlight in tree. */
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) {
background-color: inherit;
}
/* Only show 'stale expansion' info when the element gets expanded. */
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-rows > .monaco-tree-row:not(.expanded) > .content.input-output-pair > .output > .annotation::before {
content: '';
}
.hc-black .monaco-workbench .repl .repl-input-wrapper {
border-top-color: #6FC3DF;
}
.monaco-workbench .repl .repl-input-wrapper:before {
left: 8px;
position: absolute;
}
.monaco-workbench .repl .repl-input-wrapper:before {
content: '\276f';
line-height: 18px;
}
.monaco-workbench.linux .repl .repl-input-wrapper:before {
font-size: 9px;
}
/* Actions */
.monaco-workbench .debug-action.clear-repl {
background: url('clear-repl.svg') center center no-repeat;
}
.vs-dark .monaco-workbench .debug-action.clear-repl,
.hc-black .monaco-workbench .debug-action.clear-repl {
background: url('clear-repl-inverse.svg') center center no-repeat;
}
/* Output coloring */
.vs .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression > .warn {
color: #cd9731;
}
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression > .warn {
color: #cd9731;
}
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression > .warn {
color: #008000;
}
.vs .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression > .annotation {
color: #007ACC;
}
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression > .annotation {
color: #1B80B2;
}
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression > .annotation {
color: #0000FF;
}
/* ANSI Codes */
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-bold { font-weight: bold; }
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code30, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code90 { color: gray; }
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code31, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code91 { color: #BE1717; }
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code32, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code92 { color: #338A2F; }
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code33, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code93 { color: #BEB817; }
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code34, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code94 { color: darkblue; }
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code35, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code95 { color: darkmagenta; }
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code36, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code96 { color: darkcyan; }
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code37, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code97 { color: #BDBDBD; }
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code30, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code90 { color: #A0A0A0; }
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code31, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code91 { color: #A74747; }
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code32, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code92 { color: #348F34; }
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code33, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code93 { color: #5F4C29; }
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code34, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code94 { color: #6286BB; }
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code35, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code95 { color: #914191; }
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code36, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code96 { color: #218D8D; }
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code37, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code97 { color: #707070; }
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code30, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code90 { color: gray; }
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code31, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code91 { color: #A74747; }
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code32, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code92 { color: #348F34; }
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code33, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code93 { color: #5F4C29; }
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code34, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code94 { color: #6286BB; }
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code35, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code95 { color: #914191; }
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code36, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code96 { color: #218D8D; }
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code37, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code97 { color: #707070; }
/* Links */
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression a {
text-decoration: underline;
cursor: pointer;
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-bg{fill:#424242;} .icon-vs-fg{fill:#F0EFF1;}</style><path class="icon-canvas-transparent" d="M32 32h-32v-32h32v32z" id="canvas"/><path class="icon-vs-out" d="M32 28h-32v-24h32v24z" id="outline"/><path class="icon-vs-bg" d="M2 6v20h28v-20h-28zm26 18h-24v-16h24v16zm-13-8l-5.25 5.5-1.75-1.833 3.5-3.667-3.5-3.667 1.75-1.833 5.25 5.5z" id="iconBg"/><g id="iconFg"><path class="icon-vs-fg" d="M4 8v16h24v-16h-24zm5.75 13.5l-1.75-1.833 3.5-3.667-3.5-3.667 1.75-1.833 5.25 5.5-5.25 5.5z"/></g></svg>

After

Width:  |  Height:  |  Size: 686 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#1E1E1E" d="M9.3 2.1L11.4 0H5.6l-4 4 .8.8-.4.6C1.4 6.5 1 7.7 1 9c0 3.9 3.1 7 7 7s7-3.1 7-7c0-3.4-2.5-6.3-5.7-6.9zM8 12c-1.7 0-3-1.3-3-3 0-.4.1-.8.3-1.2v-.1l.3.3h5.2c.1.3.2.6.2 1 0 1.7-1.3 3-3 3z"/><path fill="#89D185" d="M8 3H7l2-2H6L3 4l3 3h3L7 5h1c2.2 0 4 1.8 4 4s-1.8 4-4 4-4-1.8-4-4c0-.6.1-1.1.4-1.6L2.9 5.9c-.6.9-.9 2-.9 3.1 0 3.3 2.7 6 6 6s6-2.7 6-6-2.7-6-6-6z"/></svg>

After

Width:  |  Height:  |  Size: 470 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#F6F6F6" d="M9.3 2.1L11.4 0H5.6l-4 4 .8.8-.4.6C1.4 6.5 1 7.7 1 9c0 3.9 3.1 7 7 7s7-3.1 7-7c0-3.4-2.5-6.3-5.7-6.9zM8 12c-1.7 0-3-1.3-3-3 0-.4.1-.8.3-1.2v-.1l.3.3h5.2c.1.3.2.6.2 1 0 1.7-1.3 3-3 3z"/><path fill="#388A34" d="M8 3H7l2-2H6L3 4l3 3h3L7 5h1c2.2 0 4 1.8 4 4s-1.8 4-4 4-4-1.8-4-4c0-.6.1-1.1.4-1.6L2.9 5.9c-.6.9-.9 2-.9 3.1 0 3.3 2.7 6 6 6s6-2.7 6-6-2.7-6-6-6z"/></svg>

After

Width:  |  Height:  |  Size: 470 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-red{fill:#e51400}.icon-vs-yellow{fill:#9CCE9C}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-bg" d="M14.414 8l-5 6H3V2h6.414l5 6z" id="outline" style="display: none;"/><path class="icon-vs-yellow" d="M13 8l-4 5H4V3h5l4 5z" id="iconBg"/><g id="iconFg"><path class="icon-vs-red" d="M10.5 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/></g></svg>

After

Width:  |  Height:  |  Size: 533 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-red{fill:#e51400}.icon-vs-yellow{fill:#CEE7CE}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-bg" d="M14.414 8l-5 6H3V2h6.414l5 6z" id="outline" style="display: none;"/><path class="icon-vs-yellow" d="M13 8l-4 5H4V3h5l4 5z" id="iconBg"/><g id="iconFg"><path class="icon-vs-red" d="M10.5 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/></g></svg>

After

Width:  |  Height:  |  Size: 533 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-yellow{fill:#9CCE9C}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-bg" d="M14.414 8l-5 6H3V2h6.414l5 6z" id="outline" style="display: none;"/><g id="iconBg"><path class="icon-vs-yellow" d="M13 8l-4 5H4V3h5l4 5z"/></g></svg>

After

Width:  |  Height:  |  Size: 427 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-yellow{fill:#CEE7CE}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-bg" d="M14.414 8l-5 6H3V2h6.414l5 6z" id="outline" style="display: none;"/><g id="iconBg"><path class="icon-vs-yellow" d="M13 8l-4 5H4V3h5l4 5z"/></g></svg>

After

Width:  |  Height:  |  Size: 427 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#2D2D30;} .icon-vs-out{fill:#2D2D30;} .icon-vs-bg{fill:#C5C5C5;} .icon-vs-action-blue{fill:#75BEFF;}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M11 13c0-1.526-1.15-2.775-2.624-2.962L12 6.414V1.586l-2 2V1H6v2.586l-2-2v4.828l3.624 3.624C6.15 10.225 5 11.474 5 13c0 1.654 1.346 3 3 3s3-1.346 3-3z" id="outline"/><path class="icon-vs-bg" d="M8 11c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .896-2 2-2z" id="iconBg"/><path class="icon-vs-action-blue" d="M8 9L5 6V4l2 2V2h2v4l2-2v2L8 9z" id="colorAction"/></svg>

After

Width:  |  Height:  |  Size: 717 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-bg{fill:#424242;} .icon-vs-action-blue{fill:#00539C;}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M11 13c0-1.526-1.15-2.775-2.624-2.962L12 6.414V1.586l-2 2V1H6v2.586l-2-2v4.828l3.624 3.624C6.15 10.225 5 11.474 5 13c0 1.654 1.346 3 3 3s3-1.346 3-3z" id="outline"/><path class="icon-vs-bg" d="M8 11c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .896-2 2-2z" id="iconBg"/><path class="icon-vs-action-blue" d="M8 9L5 6V4l2 2V2h2v4l2-2v2L8 9z" id="colorAction"/></svg>

After

Width:  |  Height:  |  Size: 717 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#2D2D30;} .icon-vs-out{fill:#2D2D30;} .icon-vs-bg{fill:#C5C5C5;} .icon-vs-action-blue{fill:#75BEFF;}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><g id="outline"><path class="icon-vs-out" d="M10 7.414l2 2V4.586l-4-4-4 4v4.828l2-2V10h4z"/><circle class="icon-vs-out" cx="8" cy="13" r="3"/></g><path class="icon-vs-bg" d="M8 11c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .896-2 2-2z" id="iconBg"/><path class="icon-vs-action-blue" d="M11 5v2L9 5v4H7V5L5 7V5l3-3 3 3z" id="colorAction"/></svg>

After

Width:  |  Height:  |  Size: 670 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-bg{fill:#424242;} .icon-vs-action-blue{fill:#00539C;}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><g id="outline"><path class="icon-vs-out" d="M10 7.414l2 2V4.586l-4-4-4 4v4.828l2-2V10h4z"/><circle class="icon-vs-out" cx="8" cy="13" r="3"/></g><path class="icon-vs-bg" d="M8 11c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .896-2 2-2z" id="iconBg"/><path class="icon-vs-action-blue" d="M11 5v2L9 5v4H7V5L5 7V5l3-3 3 3z" id="colorAction"/></svg>

After

Width:  |  Height:  |  Size: 670 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#2D2D30;} .icon-vs-out{fill:#2D2D30;} .icon-vs-bg{fill:#C5C5C5;} .icon-vs-action-blue{fill:#75BEFF;}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M8 16c-1.654 0-3-1.346-3-3s1.346-3 3-3 3 1.346 3 3-1.346 3-3 3zm7-6V4.586l-4-4V3.03C9.967 2.367 8.755 2 7.5 2 4.158 2 1.305 4.596 1.004 7.91L.904 9H4.55l.113-.872c.104-.79.528-1.474 1.13-1.923L9.587 10H15zM6.106 6c.415-.232.892-.363 1.394-.363.51 0 1.02.133 1.466.363h-2.86z" id="outline"/><path class="icon-vs-bg" d="M8 11c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .896-2 2-2z" id="iconBg"/><path class="icon-vs-action-blue" d="M3.67 8H2c.254-2.8 2.637-5 5.5-5 1.86 0 3.504.93 4.5 2.348V3l2 2v4h-4L8 7h3v-.002l.238.002C10.652 5.61 9.102 4.637 7.5 4.637 5.535 4.637 3.915 6.102 3.67 8z" id="colorAction"/></svg>

After

Width:  |  Height:  |  Size: 967 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-bg{fill:#424242;} .icon-vs-action-blue{fill:#00539C;}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M8 16c-1.654 0-3-1.346-3-3s1.346-3 3-3 3 1.346 3 3-1.346 3-3 3zm7-6V4.586l-4-4V3.03C9.967 2.367 8.755 2 7.5 2 4.158 2 1.305 4.596 1.004 7.91L.904 9H4.55l.113-.872c.104-.79.528-1.474 1.13-1.923L9.587 10H15zM6.106 6c.415-.232.892-.363 1.394-.363.51 0 1.02.133 1.466.363h-2.86z" id="outline"/><path class="icon-vs-bg" d="M8 11c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .896-2 2-2z" id="iconBg"/><path class="icon-vs-action-blue" d="M3.67 8H2c.254-2.8 2.637-5 5.5-5 1.86 0 3.504.93 4.5 2.348V3l2 2v4h-4L8 7h3v-.002l.238.002C10.652 5.61 9.102 4.637 7.5 4.637 5.535 4.637 3.915 6.102 3.67 8z" id="colorAction"/></svg>

After

Width:  |  Height:  |  Size: 967 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#2D2D30" d="M13 13h-10v-10h10v10z"/><path fill="#F48771" d="M12 12h-8v-8h8v8z"/></svg>

After

Width:  |  Height:  |  Size: 215 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#F6F6F6" d="M13 13h-10v-10h10v10z"/><path fill="#A1260D" d="M12 12h-8v-8h8v8z"/></svg>

After

Width:  |  Height:  |  Size: 215 B

View File

@@ -0,0 +1,642 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import uri from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import severity from 'vs/base/common/severity';
import Event from 'vs/base/common/event';
import { IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IModel as EditorIModel, IEditorContribution } from 'vs/editor/common/editorCommon';
import { IEditor } from 'vs/platform/editor/common/editor';
import { Position } from 'vs/editor/common/core/position';
import { ISuggestion } from 'vs/editor/common/modes';
import { Source } from 'vs/workbench/parts/debug/common/debugSource';
import { Range, IRange } from 'vs/editor/common/core/range';
import { RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
export const VIEWLET_ID = 'workbench.view.debug';
export const REPL_ID = 'workbench.panel.repl';
export const DEBUG_SERVICE_ID = 'debugService';
export const CONTEXT_DEBUG_TYPE = new RawContextKey<string>('debugType', undefined);
export const CONTEXT_DEBUG_STATE = new RawContextKey<string>('debugState', undefined);
export const CONTEXT_IN_DEBUG_MODE = new RawContextKey<boolean>('inDebugMode', false);
export const CONTEXT_NOT_IN_DEBUG_MODE: ContextKeyExpr = CONTEXT_IN_DEBUG_MODE.toNegated();
export const CONTEXT_IN_DEBUG_REPL = new RawContextKey<boolean>('inDebugRepl', false);
export const CONTEXT_NOT_IN_DEBUG_REPL: ContextKeyExpr = CONTEXT_IN_DEBUG_REPL.toNegated();
export const CONTEXT_ON_FIRST_DEBUG_REPL_LINE = new RawContextKey<boolean>('onFirsteDebugReplLine', false);
export const CONTEXT_ON_LAST_DEBUG_REPL_LINE = new RawContextKey<boolean>('onLastDebugReplLine', false);
export const CONTEXT_BREAKPOINT_WIDGET_VISIBLE = new RawContextKey<boolean>('breakpointWidgetVisible', false);
export const CONTEXT_BREAKPOINTS_FOCUSED = new RawContextKey<boolean>('breakpointsFocused', false);
export const CONTEXT_WATCH_EXPRESSIONS_FOCUSED = new RawContextKey<boolean>('watchExpressionsFocused', false);
export const CONTEXT_VARIABLES_FOCUSED = new RawContextKey<boolean>('variablesFocused', false);
export const EDITOR_CONTRIBUTION_ID = 'editor.contrib.debug';
export const DEBUG_SCHEME = 'debug';
export const INTERNAL_CONSOLE_OPTIONS_SCHEMA = {
enum: ['neverOpen', 'openOnSessionStart', 'openOnFirstSessionStart'],
default: 'openOnFirstSessionStart',
description: nls.localize('internalConsoleOptions', "Controls behavior of the internal debug console.")
};
// raw
export interface IRawModelUpdate {
threadId: number;
sessionId: string;
thread?: DebugProtocol.Thread;
callStack?: DebugProtocol.StackFrame[];
stoppedDetails?: IRawStoppedDetails;
allThreadsStopped?: boolean;
}
export interface IRawStoppedDetails {
reason: string;
description?: string;
threadId?: number;
text?: string;
totalFrames?: number;
framesErrorMessage?: string;
}
// model
export interface ITreeElement {
getId(): string;
}
export interface IReplElement extends ITreeElement {
toString(): string;
}
export interface IExpressionContainer extends ITreeElement {
hasChildren: boolean;
getChildren(): TPromise<IExpression[]>;
}
export interface IExpression extends IReplElement, IExpressionContainer {
name: string;
value: string;
valueChanged?: boolean;
type?: string;
}
export interface ISession {
root: uri;
stackTrace(args: DebugProtocol.StackTraceArguments): TPromise<DebugProtocol.StackTraceResponse>;
exceptionInfo(args: DebugProtocol.ExceptionInfoArguments): TPromise<DebugProtocol.ExceptionInfoResponse>;
scopes(args: DebugProtocol.ScopesArguments): TPromise<DebugProtocol.ScopesResponse>;
variables(args: DebugProtocol.VariablesArguments): TPromise<DebugProtocol.VariablesResponse>;
evaluate(args: DebugProtocol.EvaluateArguments): TPromise<DebugProtocol.EvaluateResponse>;
capabilities: DebugProtocol.Capabilities;
disconnect(restart?: boolean, force?: boolean): TPromise<DebugProtocol.DisconnectResponse>;
custom(request: string, args: any): TPromise<DebugProtocol.Response>;
onDidEvent: Event<DebugProtocol.Event>;
onDidInitialize: Event<DebugProtocol.InitializedEvent>;
restartFrame(args: DebugProtocol.RestartFrameArguments, threadId: number): TPromise<DebugProtocol.RestartFrameResponse>;
next(args: DebugProtocol.NextArguments): TPromise<DebugProtocol.NextResponse>;
stepIn(args: DebugProtocol.StepInArguments): TPromise<DebugProtocol.StepInResponse>;
stepOut(args: DebugProtocol.StepOutArguments): TPromise<DebugProtocol.StepOutResponse>;
continue(args: DebugProtocol.ContinueArguments): TPromise<DebugProtocol.ContinueResponse>;
pause(args: DebugProtocol.PauseArguments): TPromise<DebugProtocol.PauseResponse>;
stepBack(args: DebugProtocol.StepBackArguments): TPromise<DebugProtocol.StepBackResponse>;
reverseContinue(args: DebugProtocol.ReverseContinueArguments): TPromise<DebugProtocol.ReverseContinueResponse>;
completions(args: DebugProtocol.CompletionsArguments): TPromise<DebugProtocol.CompletionsResponse>;
setVariable(args: DebugProtocol.SetVariableArguments): TPromise<DebugProtocol.SetVariableResponse>;
source(args: DebugProtocol.SourceArguments): TPromise<DebugProtocol.SourceResponse>;
}
export enum ProcessState {
INACTIVE,
ATTACH,
LAUNCH
}
export interface IProcess extends ITreeElement {
getName(includeRoot: boolean): string;
configuration: IConfig;
session: ISession;
sources: Map<string, Source>;
state: ProcessState;
getThread(threadId: number): IThread;
getAllThreads(): IThread[];
completions(frameId: number, text: string, position: Position, overwriteBefore: number): TPromise<ISuggestion[]>;
}
export interface IThread extends ITreeElement {
/**
* Process the thread belongs to
*/
process: IProcess;
/**
* Id of the thread generated by the debug adapter backend.
*/
threadId: number;
/**
* Name of the thread.
*/
name: string;
/**
* Information about the current thread stop event. Null if thread is not stopped.
*/
stoppedDetails: IRawStoppedDetails;
/**
* Information about the exception if an 'exception' stopped event raised and DA supports the 'exceptionInfo' request, otherwise null.
*/
exceptionInfo: TPromise<IExceptionInfo>;
/**
* Gets the callstack if it has already been received from the debug
* adapter, otherwise it returns null.
*/
getCallStack(): IStackFrame[];
/**
* Invalidates the callstack cache
*/
clearCallStack(): void;
/**
* Indicates whether this thread is stopped. The callstack for stopped
* threads can be retrieved from the debug adapter.
*/
stopped: boolean;
next(): TPromise<any>;
stepIn(): TPromise<any>;
stepOut(): TPromise<any>;
stepBack(): TPromise<any>;
continue(): TPromise<any>;
pause(): TPromise<any>;
reverseContinue(): TPromise<any>;
}
export interface IScope extends IExpressionContainer {
name: string;
expensive: boolean;
range?: IRange;
}
export interface IStackFrame extends ITreeElement {
thread: IThread;
name: string;
presentationHint: string;
frameId: number;
range: IRange;
source: Source;
getScopes(): TPromise<IScope[]>;
getMostSpecificScopes(range: IRange): TPromise<IScope[]>;
restart(): TPromise<any>;
toString(): string;
openInEditor(editorService: IWorkbenchEditorService, preserveFocus?: boolean, sideBySide?: boolean): TPromise<any>;
}
export interface IEnablement extends ITreeElement {
enabled: boolean;
}
export interface IRawBreakpoint {
lineNumber: number;
column?: number;
enabled?: boolean;
condition?: string;
hitCondition?: string;
}
export interface IBreakpoint extends IEnablement {
uri: uri;
lineNumber: number;
endLineNumber?: number;
column: number;
endColumn?: number;
condition: string;
hitCondition: string;
verified: boolean;
idFromAdapter: number;
message: string;
}
export interface IFunctionBreakpoint extends IEnablement {
name: string;
verified: boolean;
idFromAdapter: number;
hitCondition: string;
}
export interface IExceptionBreakpoint extends IEnablement {
filter: string;
label: string;
}
export interface IExceptionInfo {
id?: string;
description?: string;
breakMode: string;
details?: DebugProtocol.ExceptionDetails;
}
// model interfaces
export interface IViewModel extends ITreeElement {
/**
* Returns the focused debug process or null if no process is stopped.
*/
focusedProcess: IProcess;
/**
* Returns the focused thread or null if no thread is stopped.
*/
focusedThread: IThread;
/**
* Returns the focused stack frame or null if there are no stack frames.
*/
focusedStackFrame: IStackFrame;
getSelectedExpression(): IExpression;
getSelectedFunctionBreakpoint(): IFunctionBreakpoint;
setSelectedExpression(expression: IExpression);
setSelectedFunctionBreakpoint(functionBreakpoint: IFunctionBreakpoint): void;
isMultiProcessView(): boolean;
onDidFocusProcess: Event<IProcess | undefined>;
onDidFocusStackFrame: Event<{ stackFrame: IStackFrame, explicit: boolean }>;
onDidSelectExpression: Event<IExpression>;
onDidSelectFunctionBreakpoint: Event<IFunctionBreakpoint>;
}
export interface IModel extends ITreeElement {
getProcesses(): IProcess[];
getBreakpoints(): IBreakpoint[];
areBreakpointsActivated(): boolean;
getFunctionBreakpoints(): IFunctionBreakpoint[];
getExceptionBreakpoints(): IExceptionBreakpoint[];
getWatchExpressions(): IExpression[];
getReplElements(): IReplElement[];
onDidChangeBreakpoints: Event<void>;
onDidChangeCallStack: Event<void>;
onDidChangeWatchExpressions: Event<IExpression>;
onDidChangeReplElements: Event<void>;
};
// Debug enums
export enum State {
Inactive,
Initializing,
Stopped,
Running
}
// Debug configuration interfaces
export interface IDebugConfiguration {
allowBreakpointsEverywhere: boolean;
openExplorerOnEnd: boolean;
inlineValues: boolean;
hideActionBar: boolean;
internalConsoleOptions: string;
}
export interface IGlobalConfig {
version: string;
compounds: ICompound[];
configurations: IConfig[];
}
export interface IEnvConfig {
name?: string;
type: string;
request: string;
internalConsoleOptions?: string;
preLaunchTask?: string;
__restart?: any;
__sessionId?: string;
debugServer?: number;
noDebug?: boolean;
port?: number;
}
export interface IConfig extends IEnvConfig {
windows?: IEnvConfig;
osx?: IEnvConfig;
linux?: IEnvConfig;
}
export interface ICompound {
name: string;
configurations: string[];
}
export interface IAdapterExecutable {
command?: string;
args?: string[];
}
export interface IRawEnvAdapter {
type?: string;
label?: string;
program?: string;
args?: string[];
runtime?: string;
runtimeArgs?: string[];
}
export interface IRawAdapter extends IRawEnvAdapter {
adapterExecutableCommand?: string;
enableBreakpointsFor?: { languageIds: string[] };
configurationAttributes?: any;
configurationSnippets?: IJSONSchemaSnippet[];
initialConfigurations?: any[] | string;
startSessionCommand?: string;
languages?: string[];
variables?: { [key: string]: string };
aiKey?: string;
win?: IRawEnvAdapter;
winx86?: IRawEnvAdapter;
windows?: IRawEnvAdapter;
osx?: IRawEnvAdapter;
linux?: IRawEnvAdapter;
}
export interface IDebugConfigurationProvider {
type: string;
resolveDebugConfiguration?(folderUri: uri | undefined, debugConfiguration: any): TPromise<any>;
provideDebugConfigurations?(folderUri: uri | undefined): TPromise<any[]>;
}
export interface IConfigurationManager {
/**
* Returns true if breakpoints can be set for a given editor model. Depends on mode.
*/
canSetBreakpointsIn(model: EditorIModel): boolean;
/**
* Returns null for no folder workspace. Otherwise returns a launch object corresponding to the selected debug configuration.
*/
selectedLaunch: ILaunch;
selectedName: string;
selectConfiguration(launch: ILaunch, name?: string, debugStarted?: boolean): void;
getLaunches(): ILaunch[];
/**
* Allows to register on change of selected debug configuration.
*/
onDidSelectConfiguration: Event<void>;
/**
* Returns a "startSessionCommand" contribution for an adapter with the passed type.
* If no type is specified will try to automatically pick an adapter by looking at
* the active editor language and matching it against the "languages" contribution of an adapter.
*/
getStartSessionCommand(type?: string): TPromise<{ command: string, type: string }>;
registerDebugConfigurationProvider(handle: number, debugConfigurationProvider: IDebugConfigurationProvider): void;
unregisterDebugConfigurationProvider(handle: number): void;
resolveDebugConfiguration(folderUri: uri | undefined, debugConfiguration: any): TPromise<any>;
}
export interface ILaunch {
/**
* Resource pointing to the launch.json this object is wrapping.
*/
uri: uri;
workspaceUri: uri;
name: string;
/**
* Returns a configuration with the specified name.
* Returns null if there is no configuration with the specified name.
*/
getConfiguration(name: string): IConfig;
/**
* Returns a compound with the specified name.
* Returns null if there is no compound with the specified name.
*/
getCompound(name: string): ICompound;
/**
* Returns the names of all configurations and compounds.
* Ignores configurations which are invalid.
*/
getConfigurationNames(): string[];
/**
* Returns the resolved configuration.
* Replaces os specific values, system variables, interactive variables.
*/
resolveConfiguration(config: IConfig): TPromise<IConfig>;
/**
* Opens the launch.json file. Creates if it does not exist.
*/
openConfigFile(sideBySide: boolean, type?: string): TPromise<IEditor>;
}
// Debug service interfaces
export const IDebugService = createDecorator<IDebugService>(DEBUG_SERVICE_ID);
export interface DebugEvent extends DebugProtocol.Event {
sessionId?: string;
}
export interface IDebugService {
_serviceBrand: any;
/**
* Gets the current debug state.
*/
state: State;
/**
* Allows to register on debug state changes.
*/
onDidChangeState: Event<State>;
/**
* Allows to register on new process events.
*/
onDidNewProcess: Event<IProcess>;
/**
* Allows to register on end process events.
*/
onDidEndProcess: Event<IProcess>;
/**
* Allows to register on custom DAP events.
*/
onDidCustomEvent: Event<DebugEvent>;
/**
* Gets the current configuration manager.
*/
getConfigurationManager(): IConfigurationManager;
/**
* Sets the focused stack frame and evaluates all expressions against the newly focused stack frame,
*/
focusStackFrameAndEvaluate(focusedStackFrame: IStackFrame, process?: IProcess, explicit?: boolean): TPromise<void>;
/**
* Adds new breakpoints to the model for the file specified with the uri. Notifies debug adapter of breakpoint changes.
*/
addBreakpoints(uri: uri, rawBreakpoints: IRawBreakpoint[]): TPromise<void>;
/**
* Enables or disables all breakpoints. If breakpoint is passed only enables or disables the passed breakpoint.
* Notifies debug adapter of breakpoint changes.
*/
enableOrDisableBreakpoints(enable: boolean, breakpoint?: IEnablement): TPromise<void>;
/**
* Sets the global activated property for all breakpoints.
* Notifies debug adapter of breakpoint changes.
*/
setBreakpointsActivated(activated: boolean): TPromise<void>;
/**
* Removes all breakpoints. If id is passed only removes the breakpoint associated with that id.
* Notifies debug adapter of breakpoint changes.
*/
removeBreakpoints(id?: string): TPromise<any>;
/**
* Adds a new no name function breakpoint. The function breakpoint should be renamed once user enters the name.
*/
addFunctionBreakpoint(): void;
/**
* Renames an already existing function breakpoint.
* Notifies debug adapter of breakpoint changes.
*/
renameFunctionBreakpoint(id: string, newFunctionName: string): TPromise<void>;
/**
* Removes all function breakpoints. If id is passed only removes the function breakpoint with the passed id.
* Notifies debug adapter of breakpoint changes.
*/
removeFunctionBreakpoints(id?: string): TPromise<void>;
/**
* Adds a new expression to the repl.
*/
addReplExpression(name: string): TPromise<void>;
/**
* Removes all repl expressions.
*/
removeReplExpressions(): void;
/**
* Appends the passed string to the debug repl.
*/
logToRepl(value: string, sev?: severity): void;
/**
* Adds a new watch expression and evaluates it against the debug adapter.
*/
addWatchExpression(name?: string): TPromise<void>;
/**
* Renames a watch expression and evaluates it against the debug adapter.
*/
renameWatchExpression(id: string, newName: string): TPromise<void>;
/**
* Moves a watch expression to a new possition. Used for reordering watch expressions.
*/
moveWatchExpression(id: string, position: number): void;
/**
* Removes all watch expressions. If id is passed only removes the watch expression with the passed id.
*/
removeWatchExpressions(id?: string): void;
/**
* Starts debugging. If the configOrName is not passed uses the selected configuration in the debug dropdown.
* Also saves all files, manages if compounds are present in the configuration
* and calls the startSessionCommand if an adapter registered it.
*/
startDebugging(root: uri, configOrName?: IConfig | string, noDebug?: boolean): TPromise<any>;
/**
* Creates a new debug process. Depending on the configuration will either 'launch' or 'attach'.
*/
createProcess(root: uri, config: IConfig): TPromise<IProcess>;
/**
* Find process by ID.
*/
findProcessByUUID(uuid: string): IProcess | null;
/**
* Restarts a process or creates a new one if there is no active session.
*/
restartProcess(process: IProcess): TPromise<any>;
/**
* Stops the process. If the process does not exist then stops all processes.
*/
stopProcess(process: IProcess): TPromise<any>;
/**
* Makes unavailable all sources with the passed uri. Source will appear as grayed out in callstack view.
*/
sourceIsNotAvailable(uri: uri): void;
/**
* Gets the current debug model.
*/
getModel(): IModel;
/**
* Gets the current view model.
*/
getViewModel(): IViewModel;
}
// Editor interfaces
export interface IDebugEditorContribution extends IEditorContribution {
showHover(range: Range, focus: boolean): TPromise<void>;
showBreakpointWidget(lineNumber: number, column: number): void;
closeBreakpointWidget(): void;
addLaunchConfiguration(): TPromise<any>;
}
// utils
const _formatPIIRegexp = /{([^}]+)}/g;
export function formatPII(value: string, excludePII: boolean, args: { [key: string]: string }): string {
return value.replace(_formatPIIRegexp, function (match, group) {
if (excludePII && group.length > 0 && group[0] !== '_') {
return match;
}
return args && args.hasOwnProperty(group) ?
args[group] :
match;
});
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import uri from 'vs/base/common/uri';
import { DEBUG_SCHEME } from 'vs/workbench/parts/debug/common/debug';
const UNKNOWN_SOURCE_LABEL = nls.localize('unknownSource', "Unknown Source");
export class Source {
public uri: uri;
public available: boolean;
constructor(public raw: DebugProtocol.Source) {
if (!raw) {
this.raw = { name: UNKNOWN_SOURCE_LABEL };
}
const path = this.raw.path || this.raw.name;
this.available = this.raw.name !== UNKNOWN_SOURCE_LABEL;
this.uri = this.raw.sourceReference > 0 ? uri.parse(`${DEBUG_SCHEME}:${path}`) : uri.file(path);
}
public get name() {
return this.raw.name;
}
public get origin() {
return this.raw.origin;
}
public get presentationHint() {
return this.raw.presentationHint;
}
public get reference() {
return this.raw.sourceReference;
}
public get inMemory() {
return this.uri.toString().indexOf(`${DEBUG_SCHEME}:`) === 0;
}
}

View File

@@ -0,0 +1,97 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import Event, { Emitter } from 'vs/base/common/event';
import * as debug from 'vs/workbench/parts/debug/common/debug';
export class ViewModel implements debug.IViewModel {
private _focusedStackFrame: debug.IStackFrame;
private _focusedProcess: debug.IProcess;
private selectedExpression: debug.IExpression;
private selectedFunctionBreakpoint: debug.IFunctionBreakpoint;
private _onDidFocusProcess: Emitter<debug.IProcess | undefined>;
private _onDidFocusStackFrame: Emitter<{ stackFrame: debug.IStackFrame, explicit: boolean }>;
private _onDidSelectExpression: Emitter<debug.IExpression>;
private _onDidSelectFunctionBreakpoint: Emitter<debug.IFunctionBreakpoint>;
private multiProcessView: boolean;
public changedWorkbenchViewState: boolean;
constructor() {
this._onDidFocusProcess = new Emitter<debug.IProcess | undefined>();
this._onDidFocusStackFrame = new Emitter<{ stackFrame: debug.IStackFrame, explicit: boolean }>();
this._onDidSelectExpression = new Emitter<debug.IExpression>();
this._onDidSelectFunctionBreakpoint = new Emitter<debug.IFunctionBreakpoint>();
this.changedWorkbenchViewState = false;
this.multiProcessView = false;
}
public getId(): string {
return 'root';
}
public get focusedProcess(): debug.IProcess {
return this._focusedProcess;
}
public get focusedThread(): debug.IThread {
return this._focusedStackFrame ? this._focusedStackFrame.thread : (this._focusedProcess ? this._focusedProcess.getAllThreads().pop() : null);
}
public get focusedStackFrame(): debug.IStackFrame {
return this._focusedStackFrame;
}
public setFocusedStackFrame(stackFrame: debug.IStackFrame, process: debug.IProcess, explicit: boolean): void {
this._focusedStackFrame = stackFrame;
if (process !== this._focusedProcess) {
this._focusedProcess = process;
this._onDidFocusProcess.fire(process);
}
this._onDidFocusStackFrame.fire({ stackFrame, explicit });
}
public get onDidFocusProcess(): Event<debug.IProcess> {
return this._onDidFocusProcess.event;
}
public get onDidFocusStackFrame(): Event<{ stackFrame: debug.IStackFrame, explicit: boolean }> {
return this._onDidFocusStackFrame.event;
}
public getSelectedExpression(): debug.IExpression {
return this.selectedExpression;
}
public setSelectedExpression(expression: debug.IExpression) {
this.selectedExpression = expression;
this._onDidSelectExpression.fire(expression);
}
public get onDidSelectExpression(): Event<debug.IExpression> {
return this._onDidSelectExpression.event;
}
public getSelectedFunctionBreakpoint(): debug.IFunctionBreakpoint {
return this.selectedFunctionBreakpoint;
}
public setSelectedFunctionBreakpoint(functionBreakpoint: debug.IFunctionBreakpoint): void {
this.selectedFunctionBreakpoint = functionBreakpoint;
this._onDidSelectFunctionBreakpoint.fire(functionBreakpoint);
}
public get onDidSelectFunctionBreakpoint(): Event<debug.IFunctionBreakpoint> {
return this._onDidSelectFunctionBreakpoint.event;
}
public isMultiProcessView(): boolean {
return this.multiProcessView;
}
public setMultiProcessView(isMultiProcessView: boolean): void {
this.multiProcessView = isMultiProcessView;
}
}

View File

@@ -0,0 +1,117 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const MAX_HISTORY_ENTRIES = 50;
/**
* The repl history has the following characteristics:
* - the history is stored in local storage up to N items
* - every time a expression is evaluated, it is being added to the history
* - when starting to navigate in history, the current expression is remembered to be able to go back
* - when navigating in history and making changes to any expression, these changes are remembered until a expression is evaluated
* - the navigation state is not remembered so that the user always ends up at the end of the history stack when evaluating a expression
*/
export class ReplHistory {
private historyPointer: number;
private currentExpressionStoredMarkers: boolean;
private historyOverwrites: Map<string, string>;
constructor(private history: string[]) {
this.historyPointer = this.history.length;
this.currentExpressionStoredMarkers = false;
this.historyOverwrites = new Map<string, string>();
}
public next(): string {
return this.navigate(false);
}
public previous(): string {
return this.navigate(true);
}
private navigate(previous: boolean): string {
// validate new pointer
let newPointer = -1;
if (previous && this.historyPointer > 0 && this.history.length > this.historyPointer - 1) {
newPointer = this.historyPointer - 1;
} else if (!previous && this.history.length > this.historyPointer + 1) {
newPointer = this.historyPointer + 1;
}
if (newPointer >= 0) {
// remember pointer for next navigation
this.historyPointer = newPointer;
// check for overwrite
if (this.historyOverwrites.has(newPointer.toString())) {
return this.historyOverwrites.get(newPointer.toString());
}
return this.history[newPointer];
}
return null;
}
public remember(expression: string, fromPrevious: boolean): void {
let previousPointer: number;
// this method is called after the user has navigated in the history. Therefor we need to
// restore the value of the pointer from the point when the user started the navigation.
if (fromPrevious) {
previousPointer = this.historyPointer + 1;
} else {
previousPointer = this.historyPointer - 1;
}
// when the user starts to navigate in history, add the current expression to the history
// once so that the user can always navigate back to it and does not loose its data.
if (previousPointer === this.history.length && !this.currentExpressionStoredMarkers) {
this.history.push(expression);
this.currentExpressionStoredMarkers = true;
}
// keep edits that are made to history items up until the user actually evaluates a expression
else {
this.historyOverwrites.set(previousPointer.toString(), expression);
}
}
public evaluated(expression: string): void {
// clear current expression that was stored previously to support history navigation now on evaluate
if (this.currentExpressionStoredMarkers) {
this.history.pop();
}
// keep in local history if expression provided and not equal to previous expression stored in history
if (expression && (this.history.length === 0 || this.history[this.history.length - 1] !== expression)) {
this.history.push(expression);
}
// advance History Pointer to the end
this.historyPointer = this.history.length;
// reset marker
this.currentExpressionStoredMarkers = false;
// reset overwrites
this.historyOverwrites.clear();
}
public save(): string[] {
// remove current expression from history since it was not evaluated
if (this.currentExpressionStoredMarkers) {
this.history.pop();
}
if (this.history.length > MAX_HISTORY_ENTRIES) {
this.history = this.history.splice(this.history.length - MAX_HISTORY_ENTRIES, MAX_HISTORY_ENTRIES);
}
return this.history;
}
}

View File

@@ -0,0 +1,185 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!../browser/media/debug.contribution';
import 'vs/css!../browser/media/debugHover';
import * as nls from 'vs/nls';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { Registry } from 'vs/platform/registry/common/platform';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { KeybindingsRegistry, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionRegistryExtensions } from 'vs/workbench/common/actionRegistry';
import { ToggleViewletAction, Extensions as ViewletExtensions, ViewletRegistry, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { TogglePanelAction, Extensions as PanelExtensions, PanelRegistry, PanelDescriptor } from 'vs/workbench/browser/panel';
import { VariablesView, WatchExpressionsView, CallStackView, BreakpointsView } from 'vs/workbench/parts/debug/electron-browser/debugViews';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { IDebugService, VIEWLET_ID, REPL_ID, CONTEXT_NOT_IN_DEBUG_MODE, CONTEXT_IN_DEBUG_MODE, INTERNAL_CONSOLE_OPTIONS_SCHEMA } from 'vs/workbench/parts/debug/common/debug';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { DebugEditorModelManager } from 'vs/workbench/parts/debug/browser/debugEditorModelManager';
import {
StepOverAction, ClearReplAction, FocusReplAction, StepIntoAction, StepOutAction, StartAction, RestartAction, ContinueAction, StopAction, DisconnectAction, PauseAction, AddFunctionBreakpointAction,
ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction
} from 'vs/workbench/parts/debug/browser/debugActions';
import { DebugActionsWidget } from 'vs/workbench/parts/debug/browser/debugActionsWidget';
import * as service from 'vs/workbench/parts/debug/electron-browser/debugService';
import { DebugContentProvider } from 'vs/workbench/parts/debug/browser/debugContentProvider';
import 'vs/workbench/parts/debug/electron-browser/debugEditorContribution';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import * as debugCommands from 'vs/workbench/parts/debug/electron-browser/debugCommands';
import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
import { StatusBarColorProvider } from 'vs/workbench/parts/debug/electron-browser/statusbarColorProvider';
import { ViewLocation, ViewsRegistry } from 'vs/workbench/parts/views/browser/viewsRegistry';
class OpenDebugViewletAction extends ToggleViewletAction {
public static ID = VIEWLET_ID;
public static LABEL = nls.localize('toggleDebugViewlet', "Show Debug");
constructor(
id: string,
label: string,
@IViewletService viewletService: IViewletService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService
) {
super(id, label, VIEWLET_ID, viewletService, editorService);
}
}
class OpenDebugPanelAction extends TogglePanelAction {
public static ID = 'workbench.debug.action.toggleRepl';
public static LABEL = nls.localize('toggleDebugPanel', "Debug Console");
constructor(
id: string,
label: string,
@IPanelService panelService: IPanelService,
@IPartService partService: IPartService
) {
super(id, label, REPL_ID, panelService, partService);
}
}
// register viewlet
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(new ViewletDescriptor(
'vs/workbench/parts/debug/browser/debugViewlet',
'DebugViewlet',
VIEWLET_ID,
nls.localize('debug', "Debug"),
'debug',
40
));
const openViewletKb: IKeybindings = {
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_D
};
const openPanelKb: IKeybindings = {
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Y
};
// register repl panel
Registry.as<PanelRegistry>(PanelExtensions.Panels).registerPanel(new PanelDescriptor(
'vs/workbench/parts/debug/electron-browser/repl',
'Repl',
REPL_ID,
nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'),
'repl',
30,
OpenDebugPanelAction.ID
));
Registry.as<PanelRegistry>(PanelExtensions.Panels).setDefaultPanelId(REPL_ID);
// Register default debug views
ViewsRegistry.registerViews([{ id: 'workbench.debug.variablesView', name: nls.localize('variables', "Variables"), ctor: VariablesView, order: 10, size: 40, location: ViewLocation.Debug, canToggleVisibility: true }]);
ViewsRegistry.registerViews([{ id: 'workbench.debug.watchExpressionsView', name: nls.localize('watch', "Watch"), ctor: WatchExpressionsView, order: 20, size: 10, location: ViewLocation.Debug, canToggleVisibility: true }]);
ViewsRegistry.registerViews([{ id: 'workbench.debug.callStackView', name: nls.localize('callStack', "Call Stack"), ctor: CallStackView, order: 30, size: 30, location: ViewLocation.Debug, canToggleVisibility: true }]);
ViewsRegistry.registerViews([{ id: 'workbench.debug.breakPointsView', name: nls.localize('breakpoints', "Breakpoints"), ctor: BreakpointsView, order: 40, size: 20, location: ViewLocation.Debug, canToggleVisibility: true }]);
// register action to open viewlet
const registry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionRegistryExtensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenDebugPanelAction, OpenDebugPanelAction.ID, OpenDebugPanelAction.LABEL, openPanelKb), 'View: Debug Console', nls.localize('view', "View"));
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenDebugViewletAction, OpenDebugViewletAction.ID, OpenDebugViewletAction.LABEL, openViewletKb), 'View: Show Debug', nls.localize('view', "View"));
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugEditorModelManager);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugActionsWidget);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugContentProvider);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(StatusBarColorProvider);
const debugCategory = nls.localize('debugCategory', "Debug");
registry.registerWorkbenchAction(new SyncActionDescriptor(
StartAction, StartAction.ID, StartAction.LABEL, { primary: KeyCode.F5 }, CONTEXT_NOT_IN_DEBUG_MODE), 'Debug: Start Debugging', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StepOverAction, StepOverAction.ID, StepOverAction.LABEL, { primary: KeyCode.F10 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Step Over', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StepIntoAction, StepIntoAction.ID, StepIntoAction.LABEL, { primary: KeyCode.F11 }, CONTEXT_IN_DEBUG_MODE, KeybindingsRegistry.WEIGHT.workbenchContrib(1)), 'Debug: Step Into', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StepOutAction, StepOutAction.ID, StepOutAction.LABEL, { primary: KeyMod.Shift | KeyCode.F11 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Step Out', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(RestartAction, RestartAction.ID, RestartAction.LABEL, { primary: KeyMod.Shift | KeyMod.CtrlCmd | KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Restart', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(StopAction, StopAction.ID, StopAction.LABEL, { primary: KeyMod.Shift | KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Stop', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(DisconnectAction, DisconnectAction.ID, DisconnectAction.LABEL), 'Debug: Disconnect', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(ContinueAction, ContinueAction.ID, ContinueAction.LABEL, { primary: KeyCode.F5 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Continue', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(PauseAction, PauseAction.ID, PauseAction.LABEL, { primary: KeyCode.F6 }, CONTEXT_IN_DEBUG_MODE), 'Debug: Pause', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureAction, ConfigureAction.ID, ConfigureAction.LABEL), 'Debug: Open launch.json', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(AddFunctionBreakpointAction, AddFunctionBreakpointAction.ID, AddFunctionBreakpointAction.LABEL), 'Debug: Add Function Breakpoint', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(ReapplyBreakpointsAction, ReapplyBreakpointsAction.ID, ReapplyBreakpointsAction.LABEL), 'Debug: Reapply All Breakpoints', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(RunAction, RunAction.ID, RunAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.F5 }, CONTEXT_NOT_IN_DEBUG_MODE), 'Debug: Start Without Debugging', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(RemoveAllBreakpointsAction, RemoveAllBreakpointsAction.ID, RemoveAllBreakpointsAction.LABEL), 'Debug: Remove All Breakpoints', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(EnableAllBreakpointsAction, EnableAllBreakpointsAction.ID, EnableAllBreakpointsAction.LABEL), 'Debug: Enable All Breakpoints', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(DisableAllBreakpointsAction, DisableAllBreakpointsAction.ID, DisableAllBreakpointsAction.LABEL), 'Debug: Disable All Breakpoints', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(ClearReplAction, ClearReplAction.ID, ClearReplAction.LABEL), 'Debug: Clear Console', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusReplAction, FocusReplAction.ID, FocusReplAction.LABEL), 'Debug: Focus Debug Console', debugCategory);
registry.registerWorkbenchAction(new SyncActionDescriptor(SelectAndStartAction, SelectAndStartAction.ID, SelectAndStartAction.LABEL), 'Debug: Select and Start Debugging', debugCategory);
// Register Quick Open
(<IQuickOpenRegistry>Registry.as(QuickOpenExtensions.Quickopen)).registerQuickOpenHandler(
new QuickOpenHandlerDescriptor(
'vs/workbench/parts/debug/browser/debugQuickOpen',
'DebugQuickOpenHandler',
'debug ',
'inLaunchConfigurationsPicker',
nls.localize('debugCommands', "Debug Configuration")
)
);
// register service
registerSingleton(IDebugService, service.DebugService);
// Register configuration
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
configurationRegistry.registerConfiguration({
id: 'debug',
order: 20,
title: nls.localize('debugConfigurationTitle', "Debug"),
type: 'object',
properties: {
'debug.allowBreakpointsEverywhere': {
type: 'boolean',
description: nls.localize({ comment: ['This is the description for a setting'], key: 'allowBreakpointsEverywhere' }, "Allows setting breakpoint in any file"),
default: false
},
'debug.openExplorerOnEnd': {
type: 'boolean',
description: nls.localize({ comment: ['This is the description for a setting'], key: 'openExplorerOnEnd' }, "Automatically open explorer view on the end of a debug session"),
default: false
},
'debug.inlineValues': {
type: 'boolean',
description: nls.localize({ comment: ['This is the description for a setting'], key: 'inlineValues' }, "Show variable values inline in editor while debugging"),
default: false
},
'debug.hideActionBar': {
type: 'boolean',
description: nls.localize({ comment: ['This is the description for a setting'], key: 'hideActionBar' }, "Controls if the floating debug action bar should be hidden"),
default: false
},
'debug.internalConsoleOptions': INTERNAL_CONSOLE_OPTIONS_SCHEMA,
'launch': {
type: 'object',
description: nls.localize({ comment: ['This is the description for a setting'], key: 'launch' }, "Global debug launch configuration. Should be used as an alternative to 'launch.json' that is shared across workspaces"),
default: {}
}
}
});
debugCommands.registerCommands();

View File

@@ -0,0 +1,225 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import uri from 'vs/base/common/uri';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { TPromise } from 'vs/base/common/winjs.base';
import severity from 'vs/base/common/severity';
import { List } from 'vs/base/browser/ui/list/listWidget';
import * as errors from 'vs/base/common/errors';
import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IListService } from 'vs/platform/list/browser/listService';
import { IMessageService } from 'vs/platform/message/common/message';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IDebugService, IConfig, IEnablement, CONTEXT_NOT_IN_DEBUG_MODE, CONTEXT_IN_DEBUG_MODE, CONTEXT_BREAKPOINTS_FOCUSED, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_VARIABLES_FOCUSED, EDITOR_CONTRIBUTION_ID, IDebugEditorContribution } from 'vs/workbench/parts/debug/common/debug';
import { Expression, Variable, Breakpoint, FunctionBreakpoint } from 'vs/workbench/parts/debug/common/debugModel';
import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
export function registerCommands(): void {
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: '_workbench.startDebug',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
handler(accessor: ServicesAccessor, configurationOrName: IConfig | string, folderUri?: uri) {
const debugService = accessor.get(IDebugService);
if (!configurationOrName) {
configurationOrName = debugService.getConfigurationManager().selectedName;
}
if (!folderUri) {
const selectedLaunch = debugService.getConfigurationManager().selectedLaunch;
folderUri = selectedLaunch ? selectedLaunch.workspaceUri : undefined;
}
if (typeof configurationOrName === 'string') {
debugService.startDebugging(folderUri, configurationOrName);
} else {
debugService.createProcess(folderUri, configurationOrName);
}
},
when: CONTEXT_NOT_IN_DEBUG_MODE,
primary: undefined
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.customDebugRequest',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
handler(accessor: ServicesAccessor, request: string, requestArgs: any) {
const process = accessor.get(IDebugService).getViewModel().focusedProcess;
if (process) {
return process.session.custom(request, requestArgs);
}
return undefined;
},
when: CONTEXT_IN_DEBUG_MODE,
primary: undefined
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.logToDebugConsole',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
handler(accessor: ServicesAccessor, value: string) {
if (typeof value === 'string') {
const debugService = accessor.get(IDebugService);
// Use warning as severity to get the orange color for messages coming from the debug extension
debugService.logToRepl(value, severity.Warning);
}
},
when: undefined,
primary: undefined
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.toggleBreakpoint',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(5),
when: CONTEXT_BREAKPOINTS_FOCUSED,
primary: KeyCode.Space,
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.getFocused();
// Tree only
if (!(focused instanceof List)) {
const tree = focused;
const element = <IEnablement>tree.getFocus();
debugService.enableOrDisableBreakpoints(!element.enabled, element).done(null, errors.onUnexpectedError);
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.renameWatchExpression',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(5),
when: CONTEXT_WATCH_EXPRESSIONS_FOCUSED,
primary: KeyCode.F2,
mac: { primary: KeyCode.Enter },
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.getFocused();
// Tree only
if (!(focused instanceof List)) {
const element = focused.getFocus();
if (element instanceof Expression) {
debugService.getViewModel().setSelectedExpression(element);
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.setVariable',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(5),
when: CONTEXT_VARIABLES_FOCUSED,
primary: KeyCode.F2,
mac: { primary: KeyCode.Enter },
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.getFocused();
// Tree only
if (!(focused instanceof List)) {
const element = focused.getFocus();
if (element instanceof Variable) {
debugService.getViewModel().setSelectedExpression(element);
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.removeWatchExpression',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: CONTEXT_WATCH_EXPRESSIONS_FOCUSED,
primary: KeyCode.Delete,
mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace },
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.getFocused();
// Tree only
if (!(focused instanceof List)) {
const element = focused.getFocus();
if (element instanceof Expression) {
debugService.removeWatchExpressions(element.getId());
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.removeBreakpoint',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: CONTEXT_BREAKPOINTS_FOCUSED,
primary: KeyCode.Delete,
mac: { primary: KeyMod.CtrlCmd | KeyCode.Backspace },
handler: (accessor) => {
const listService = accessor.get(IListService);
const debugService = accessor.get(IDebugService);
const focused = listService.getFocused();
// Tree only
if (!(focused instanceof List)) {
const element = focused.getFocus();
if (element instanceof Breakpoint) {
debugService.removeBreakpoints(element.getId()).done(null, errors.onUnexpectedError);
} else if (element instanceof FunctionBreakpoint) {
debugService.removeFunctionBreakpoints(element.getId()).done(null, errors.onUnexpectedError);
}
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.installAdditionalDebuggers',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: undefined,
primary: undefined,
handler: (accessor) => {
const viewletService = accessor.get(IViewletService);
return viewletService.openViewlet(EXTENSIONS_VIEWLET_ID, true)
.then(viewlet => viewlet as IExtensionsViewlet)
.then(viewlet => {
viewlet.search('tag:debuggers @sort:installs');
viewlet.focus();
});
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'debug.addConfiguration',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(),
when: undefined,
primary: undefined,
handler: (accessor, workspaceUri: string) => {
const manager = accessor.get(IDebugService).getConfigurationManager();
if (!accessor.get(IWorkspaceContextService).hasWorkspace()) {
accessor.get(IMessageService).show(severity.Info, nls.localize('noFolderDebugConfig', "Please first open a folder in order to do advanced debug configuration."));
return TPromise.as(null);
}
const launch = manager.getLaunches().filter(l => l.workspaceUri.toString() === workspaceUri).pop() || manager.selectedLaunch;
return launch.openConfigFile(false).done(editor => {
if (editor) {
const codeEditor = <ICommonCodeEditor>editor.getControl();
if (codeEditor) {
return codeEditor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).addLaunchConfiguration();
}
}
return undefined;
});
}
});
}

View File

@@ -0,0 +1,593 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import Event, { Emitter } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import * as strings from 'vs/base/common/strings';
import { first } from 'vs/base/common/arrays';
import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import * as objects from 'vs/base/common/objects';
import uri from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import * as paths from 'vs/base/common/paths';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { IModel, isCommonCodeEditor } from 'vs/editor/common/editorCommon';
import { IEditor } from 'vs/platform/editor/common/editor';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import * as extensionsRegistry from 'vs/platform/extensions/common/extensionsRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IFileService } from 'vs/platform/files/common/files';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IDebugConfigurationProvider, IRawAdapter, ICompound, IDebugConfiguration, DEBUG_SCHEME, IConfig, IEnvConfig, IGlobalConfig, IConfigurationManager, ILaunch } from 'vs/workbench/parts/debug/common/debug';
import { Adapter } from 'vs/workbench/parts/debug/node/debugAdapter';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
// debuggers extension point
export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint<IRawAdapter[]>('debuggers', [], {
description: nls.localize('vscode.extension.contributes.debuggers', 'Contributes debug adapters.'),
type: 'array',
defaultSnippets: [{ body: [{ type: '', extensions: [] }] }],
items: {
type: 'object',
defaultSnippets: [{ body: { type: '', program: '', runtime: '', enableBreakpointsFor: { languageIds: [''] } } }],
properties: {
type: {
description: nls.localize('vscode.extension.contributes.debuggers.type', "Unique identifier for this debug adapter."),
type: 'string'
},
label: {
description: nls.localize('vscode.extension.contributes.debuggers.label', "Display name for this debug adapter."),
type: 'string'
},
program: {
description: nls.localize('vscode.extension.contributes.debuggers.program', "Path to the debug adapter program. Path is either absolute or relative to the extension folder."),
type: 'string'
},
args: {
description: nls.localize('vscode.extension.contributes.debuggers.args', "Optional arguments to pass to the adapter."),
type: 'array'
},
runtime: {
description: nls.localize('vscode.extension.contributes.debuggers.runtime', "Optional runtime in case the program attribute is not an executable but requires a runtime."),
type: 'string'
},
runtimeArgs: {
description: nls.localize('vscode.extension.contributes.debuggers.runtimeArgs', "Optional runtime arguments."),
type: 'array'
},
variables: {
description: nls.localize('vscode.extension.contributes.debuggers.variables', "Mapping from interactive variables (e.g ${action.pickProcess}) in `launch.json` to a command."),
type: 'object'
},
initialConfigurations: {
description: nls.localize('vscode.extension.contributes.debuggers.initialConfigurations', "Configurations for generating the initial \'launch.json\'."),
type: ['array', 'string'],
},
languages: {
description: nls.localize('vscode.extension.contributes.debuggers.languages', "List of languages for which the debug extension could be considered the \"default debugger\"."),
type: 'array'
},
adapterExecutableCommand: {
description: nls.localize('vscode.extension.contributes.debuggers.adapterExecutableCommand', "If specified VS Code will call this command to determine the executable path of the debug adapter and the arguments to pass."),
type: 'string'
},
startSessionCommand: {
description: nls.localize('vscode.extension.contributes.debuggers.startSessionCommand', "If specified VS Code will call this command for the \"debug\" or \"run\" actions targeted for this extension."),
type: 'string'
},
configurationSnippets: {
description: nls.localize('vscode.extension.contributes.debuggers.configurationSnippets', "Snippets for adding new configurations in \'launch.json\'."),
type: 'array'
},
configurationAttributes: {
description: nls.localize('vscode.extension.contributes.debuggers.configurationAttributes', "JSON schema configurations for validating \'launch.json\'."),
type: 'object'
},
windows: {
description: nls.localize('vscode.extension.contributes.debuggers.windows', "Windows specific settings."),
type: 'object',
properties: {
runtime: {
description: nls.localize('vscode.extension.contributes.debuggers.windows.runtime', "Runtime used for Windows."),
type: 'string'
}
}
},
osx: {
description: nls.localize('vscode.extension.contributes.debuggers.osx', "OS X specific settings."),
type: 'object',
properties: {
runtime: {
description: nls.localize('vscode.extension.contributes.debuggers.osx.runtime', "Runtime used for OSX."),
type: 'string'
}
}
},
linux: {
description: nls.localize('vscode.extension.contributes.debuggers.linux', "Linux specific settings."),
type: 'object',
properties: {
runtime: {
description: nls.localize('vscode.extension.contributes.debuggers.linux.runtime', "Runtime used for Linux."),
type: 'string'
}
}
}
}
}
});
interface IRawBreakpointContribution {
language: string;
}
// breakpoints extension point #9037
const breakpointsExtPoint = extensionsRegistry.ExtensionsRegistry.registerExtensionPoint<IRawBreakpointContribution[]>('breakpoints', [], {
description: nls.localize('vscode.extension.contributes.breakpoints', 'Contributes breakpoints.'),
type: 'array',
defaultSnippets: [{ body: [{ language: '' }] }],
items: {
type: 'object',
defaultSnippets: [{ body: { language: '' } }],
properties: {
language: {
description: nls.localize('vscode.extension.contributes.breakpoints.language', "Allow breakpoints for this language."),
type: 'string'
},
}
}
});
// debug general schema
export const schemaId = 'vscode://schemas/launch';
const defaultCompound: ICompound = { name: 'Compound', configurations: [] };
const schema: IJSONSchema = {
id: schemaId,
type: 'object',
title: nls.localize('app.launch.json.title', "Launch"),
required: ['version', 'configurations'],
default: { version: '0.2.0', configurations: [], compounds: [] },
properties: {
version: {
type: 'string',
description: nls.localize('app.launch.json.version', "Version of this file format."),
default: '0.2.0'
},
configurations: {
type: 'array',
description: nls.localize('app.launch.json.configurations', "List of configurations. Add new configurations or edit existing ones by using IntelliSense."),
items: {
defaultSnippets: [],
'type': 'object',
oneOf: []
}
},
compounds: {
type: 'array',
description: nls.localize('app.launch.json.compounds', "List of compounds. Each compound references multiple configurations which will get launched together."),
items: {
type: 'object',
required: ['name', 'configurations'],
properties: {
name: {
type: 'string',
description: nls.localize('app.launch.json.compound.name', "Name of compound. Appears in the launch configuration drop down menu.")
},
configurations: {
type: 'array',
default: [],
items: {
type: 'string'
},
description: nls.localize('app.launch.json.compounds.configurations', "Names of configurations that will be started as part of this compound.")
}
},
default: defaultCompound
},
default: [
defaultCompound
]
}
}
};
const jsonRegistry = <IJSONContributionRegistry>Registry.as(JSONExtensions.JSONContribution);
jsonRegistry.registerSchema(schemaId, schema);
const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname';
const DEBUG_SELECTED_ROOT = 'debug.selectedroot';
export class ConfigurationManager implements IConfigurationManager {
private adapters: Adapter[];
private breakpointModeIdsSet = new Set<string>();
private launches: ILaunch[];
private _selectedName: string;
private _selectedLaunch: ILaunch;
private toDispose: IDisposable[];
private _onDidSelectConfigurationName = new Emitter<void>();
private _providers: Map<number, IDebugConfigurationProvider>;
constructor(
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@IFileService private fileService: IFileService,
@ITelemetryService private telemetryService: ITelemetryService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IConfigurationService private configurationService: IConfigurationService,
@IQuickOpenService private quickOpenService: IQuickOpenService,
@IConfigurationResolverService private configurationResolverService: IConfigurationResolverService,
@IInstantiationService private instantiationService: IInstantiationService,
@ICommandService private commandService: ICommandService,
@IStorageService private storageService: IStorageService,
@ILifecycleService lifecycleService: ILifecycleService,
) {
this._providers = new Map<number, IDebugConfigurationProvider>();
this.adapters = [];
this.toDispose = [];
this.registerListeners(lifecycleService);
this.initLaunches();
const previousSelectedRoot = this.storageService.get(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE);
const filtered = this.launches.filter(l => l.workspaceUri.toString() === previousSelectedRoot);
const launchToSelect = filtered.length ? filtered[0] : this.launches.length ? this.launches[0] : undefined;
this.selectConfiguration(launchToSelect, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE));
}
public registerDebugConfigurationProvider(handle: number, debugConfigurationProvider: IDebugConfigurationProvider): void {
if (!debugConfigurationProvider) {
return;
}
this._providers.set(handle, debugConfigurationProvider);
const adapter = this.getAdapter(debugConfigurationProvider.type);
if (adapter) {
adapter.hasConfigurationProvider = true;
}
}
public unregisterDebugConfigurationProvider(handle: number): boolean {
return this._providers.delete(handle);
}
public resolveDebugConfiguration(folderUri: uri | undefined, debugConfiguration: any): TPromise<any> {
// collect all candidates
const providers: IDebugConfigurationProvider[] = [];
this._providers.forEach(provider => {
if (provider.type === debugConfiguration.type && provider.resolveDebugConfiguration) {
providers.push(provider);
}
});
// pipe the config through the promises sequentially
return providers.reduce((promise, provider) => {
return promise.then(config => {
return provider.resolveDebugConfiguration(folderUri, config);
});
}, TPromise.as(debugConfiguration));
}
public provideDebugConfigurations(folderUri: uri | undefined, type: string): TPromise<any[]> {
// collect all candidates
const configs: TPromise<any[]>[] = [];
this._providers.forEach(provider => {
if (provider.type === type && provider.provideDebugConfigurations) {
configs.push(provider.provideDebugConfigurations(folderUri));
}
});
// combine all configs into one array
return TPromise.join(configs).then(results => {
return [].concat.apply([], results);
});
}
private registerListeners(lifecycleService: ILifecycleService): void {
debuggersExtPoint.setHandler((extensions) => {
extensions.forEach(extension => {
extension.value.forEach(rawAdapter => {
if (!rawAdapter.type || (typeof rawAdapter.type !== 'string')) {
extension.collector.error(nls.localize('debugNoType', "Debug adapter 'type' can not be omitted and must be of type 'string'."));
}
if (rawAdapter.enableBreakpointsFor) {
rawAdapter.enableBreakpointsFor.languageIds.forEach(modeId => {
this.breakpointModeIdsSet.add(modeId);
});
}
const duplicate = this.adapters.filter(a => a.type === rawAdapter.type).pop();
if (duplicate) {
duplicate.merge(rawAdapter, extension.description);
} else {
this.adapters.push(this.instantiationService.createInstance(Adapter, rawAdapter, extension.description));
}
});
});
// update the schema to include all attributes, snippets and types from extensions.
this.adapters.forEach(adapter => {
const items = (<IJSONSchema>schema.properties['configurations'].items);
const schemaAttributes = adapter.getSchemaAttributes();
if (schemaAttributes) {
items.oneOf.push(...schemaAttributes);
}
const configurationSnippets = adapter.configurationSnippets;
if (configurationSnippets) {
items.defaultSnippets.push(...configurationSnippets);
}
});
});
breakpointsExtPoint.setHandler(extensions => {
extensions.forEach(ext => {
ext.value.forEach(breakpoints => {
this.breakpointModeIdsSet.add(breakpoints.language);
});
});
});
this.toDispose.push(this.contextService.onDidChangeWorkspaceRoots(() => {
this.initLaunches();
const toSelect = this.selectedLaunch && this.selectedLaunch.getConfigurationNames().length ? this.selectedLaunch : first(this.launches, l => !!l.getConfigurationNames().length, this.launches.length ? this.launches[0] : undefined);
this.selectConfiguration(toSelect);
}));
this.toDispose.push(lifecycleService.onShutdown(this.store, this));
}
private initLaunches(): void {
const workspace = this.contextService.getWorkspace();
this.launches = workspace ? workspace.roots.map(root => this.instantiationService.createInstance(Launch, this, root)) : [];
if (this.launches.indexOf(this._selectedLaunch) === -1) {
this._selectedLaunch = undefined;
}
}
public getLaunches(): ILaunch[] {
return this.launches;
}
public get selectedLaunch(): ILaunch {
return this._selectedLaunch;
}
public get selectedName(): string {
return this._selectedName;
}
public get onDidSelectConfiguration(): Event<void> {
return this._onDidSelectConfigurationName.event;
}
public selectConfiguration(launch: ILaunch, name?: string, debugStarted?: boolean): void {
const previousLaunch = this._selectedLaunch;
const previousName = this._selectedName;
this._selectedLaunch = launch;
const names = launch ? launch.getConfigurationNames() : [];
if (name && names.indexOf(name) >= 0) {
this._selectedName = name;
}
if (names.indexOf(this.selectedName) === -1) {
this._selectedName = names.length ? names[0] : undefined;
}
if (this.selectedLaunch !== previousLaunch || this.selectedName !== previousName) {
this._onDidSelectConfigurationName.fire();
}
}
public canSetBreakpointsIn(model: IModel): boolean {
if (model.uri.scheme !== Schemas.file && model.uri.scheme !== DEBUG_SCHEME) {
return false;
}
if (this.configurationService.getConfiguration<IDebugConfiguration>('debug').allowBreakpointsEverywhere) {
return true;
}
const modeId = model ? model.getLanguageIdentifier().language : null;
return this.breakpointModeIdsSet.has(modeId);
}
public getAdapter(type: string): Adapter {
return this.adapters.filter(adapter => strings.equalsIgnoreCase(adapter.type, type)).pop();
}
public guessAdapter(type?: string): TPromise<Adapter> {
if (type) {
const adapter = this.getAdapter(type);
return TPromise.as(adapter);
}
const editor = this.editorService.getActiveEditor();
if (editor) {
const codeEditor = editor.getControl();
if (isCommonCodeEditor(codeEditor)) {
const model = codeEditor.getModel();
const language = model ? model.getLanguageIdentifier().language : undefined;
const adapters = this.adapters.filter(a => a.languages && a.languages.indexOf(language) >= 0);
if (adapters.length === 1) {
return TPromise.as(adapters[0]);
}
}
}
return this.quickOpenService.pick([...this.adapters.filter(a => a.hasInitialConfiguration() || a.hasConfigurationProvider), { label: 'More...', separator: { border: true } }], { placeHolder: nls.localize('selectDebug', "Select Environment") })
.then(picked => {
if (picked instanceof Adapter) {
return picked;
}
if (picked) {
this.commandService.executeCommand('debug.installAdditionalDebuggers');
}
return undefined;
});
}
public getStartSessionCommand(type?: string): TPromise<{ command: string, type: string }> {
return this.guessAdapter(type).then(adapter => {
if (adapter) {
return {
command: adapter.startSessionCommand,
type: adapter.type
};
}
return undefined;
});
}
private store(): void {
this.storageService.store(DEBUG_SELECTED_CONFIG_NAME_KEY, this.selectedName, StorageScope.WORKSPACE);
if (this._selectedLaunch) {
this.storageService.store(DEBUG_SELECTED_ROOT, this._selectedLaunch.workspaceUri.toString(), StorageScope.WORKSPACE);
}
}
public dispose(): void {
this.toDispose = dispose(this.toDispose);
}
}
class Launch implements ILaunch {
public name: string;
constructor(
private configurationManager: ConfigurationManager,
public workspaceUri: uri,
@IFileService private fileService: IFileService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IConfigurationService private configurationService: IConfigurationService,
@IConfigurationResolverService private configurationResolverService: IConfigurationResolverService,
) {
this.name = paths.basename(this.workspaceUri.fsPath);
}
public getCompound(name: string): ICompound {
const config = this.configurationService.getConfiguration<IGlobalConfig>('launch', { resource: this.workspaceUri });
if (!config || !config.compounds) {
return null;
}
return config.compounds.filter(compound => compound.name === name).pop();
}
public getConfigurationNames(): string[] {
const config = this.configurationService.getConfiguration<IGlobalConfig>('launch', { resource: this.workspaceUri });
if (!config || !config.configurations) {
return [];
} else {
const names = config.configurations.filter(cfg => cfg && typeof cfg.name === 'string').map(cfg => cfg.name);
if (names.length > 0 && config.compounds) {
if (config.compounds) {
names.push(...config.compounds.filter(compound => typeof compound.name === 'string' && compound.configurations && compound.configurations.length)
.map(compound => compound.name));
}
}
return names;
}
}
public getConfiguration(name: string): IConfig {
const config = this.configurationService.getConfiguration<IGlobalConfig>('launch', { resource: this.workspaceUri });
if (!config || !config.configurations) {
return null;
}
return config.configurations.filter(config => config && config.name === name).shift();
}
public resolveConfiguration(config: IConfig): TPromise<IConfig> {
const result = objects.deepClone(config) as IConfig;
// Set operating system specific properties #1873
const setOSProperties = (flag: boolean, osConfig: IEnvConfig) => {
if (flag && osConfig) {
Object.keys(osConfig).forEach(key => {
result[key] = osConfig[key];
});
}
};
setOSProperties(isWindows, result.windows);
setOSProperties(isMacintosh, result.osx);
setOSProperties(isLinux, result.linux);
// massage configuration attributes - append workspace path to relatvie paths, substitute variables in paths.
Object.keys(result).forEach(key => {
result[key] = this.configurationResolverService.resolveAny(this.workspaceUri, result[key]);
});
const adapter = this.configurationManager.getAdapter(result.type);
return this.configurationResolverService.resolveInteractiveVariables(result, adapter ? adapter.variables : null);
}
public get uri(): uri {
return uri.file(paths.join(this.workspaceUri.fsPath, '/.vscode/launch.json'));
}
public openConfigFile(sideBySide: boolean, type?: string): TPromise<IEditor> {
const resource = this.uri;
let configFileCreated = false;
return this.fileService.resolveContent(resource).then(content => content, err => {
// launch.json not found: create one by collecting launch configs from debugConfigProviders
return this.configurationManager.guessAdapter(type).then(adapter => {
if (adapter) {
return this.configurationManager.provideDebugConfigurations(this.workspaceUri, adapter.type).then(initialConfigs => {
return adapter.getInitialConfigurationContent(this.workspaceUri, initialConfigs);
});
} else {
return undefined;
}
}).then(content => {
if (!content) {
return undefined;
}
configFileCreated = true;
return this.fileService.updateContent(resource, content).then(() => {
// convert string into IContent; see #32135
return { value: content };
});
});
}).then(content => {
if (!content) {
return undefined;
}
const index = content.value.indexOf(`"${this.configurationManager.selectedName}"`);
let startLineNumber = 1;
for (let i = 0; i < index; i++) {
if (content.value.charAt(i) === '\n') {
startLineNumber++;
}
}
const selection = startLineNumber > 1 ? { startLineNumber, startColumn: 4 } : undefined;
return this.editorService.openEditor({
resource: resource,
options: {
forceOpen: true,
selection,
pinned: configFileCreated, // pin only if config file is created #8727
revealIfVisible: true
},
}, sideBySide);
}, (error) => {
throw new Error(nls.localize('DebugConfig.failed', "Unable to create 'launch.json' file inside the '.vscode' folder ({0}).", error));
});
}
}

View File

@@ -0,0 +1,620 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import * as errors from 'vs/base/common/errors';
import { TPromise } from 'vs/base/common/winjs.base';
import { RunOnceScheduler } from 'vs/base/common/async';
import * as lifecycle from 'vs/base/common/lifecycle';
import * as env from 'vs/base/common/platform';
import uri from 'vs/base/common/uri';
import { visit } from 'vs/base/common/json';
import { Constants } from 'vs/editor/common/core/uint';
import { IAction, Action } from 'vs/base/common/actions';
import { KeyCode } from 'vs/base/common/keyCodes';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { StandardTokenType } from 'vs/editor/common/modes';
import { DEFAULT_WORD_REGEXP } from 'vs/editor/common/model/wordHelper';
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { IDecorationOptions, IModelDecorationOptions, IModelDeltaDecoration, TrackedRangeStickiness } from 'vs/editor/common/editorCommon';
import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService';
import { Range } from 'vs/editor/common/core/range';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService, ContextSubMenu } from 'vs/platform/contextview/browser/contextView';
import { DebugHoverWidget } from 'vs/workbench/parts/debug/electron-browser/debugHover';
import { RemoveBreakpointAction, EditConditionalBreakpointAction, EnableBreakpointAction, DisableBreakpointAction, AddConditionalBreakpointAction } from 'vs/workbench/parts/debug/browser/debugActions';
import { IDebugEditorContribution, IDebugService, State, IBreakpoint, EDITOR_CONTRIBUTION_ID, CONTEXT_BREAKPOINT_WIDGET_VISIBLE, IStackFrame, IDebugConfiguration, IExpression, IExceptionInfo } from 'vs/workbench/parts/debug/common/debug';
import { BreakpointWidget } from 'vs/workbench/parts/debug/browser/breakpointWidget';
import { ExceptionWidget } from 'vs/workbench/parts/debug/browser/exceptionWidget';
import { FloatingClickWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
import { IListService } from 'vs/platform/list/browser/listService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { Position } from 'vs/editor/common/core/position';
import { CoreEditingCommands } from 'vs/editor/common/controller/coreCommands';
import { first } from 'vs/base/common/arrays';
const HOVER_DELAY = 300;
const LAUNCH_JSON_REGEX = /launch\.json$/;
const REMOVE_INLINE_VALUES_DELAY = 100;
const INLINE_VALUE_DECORATION_KEY = 'inlinevaluedecoration';
const MAX_NUM_INLINE_VALUES = 100; // JS Global scope can have 700+ entries. We want to limit ourselves for perf reasons
const MAX_INLINE_DECORATOR_LENGTH = 150; // Max string length of each inline decorator when debugging. If exceeded ... is added
const MAX_TOKENIZATION_LINE_LEN = 500; // If line is too long, then inline values for the line are skipped
@editorContribution
export class DebugEditorContribution implements IDebugEditorContribution {
private toDispose: lifecycle.IDisposable[];
private hoverWidget: DebugHoverWidget;
private showHoverScheduler: RunOnceScheduler;
private hideHoverScheduler: RunOnceScheduler;
private removeInlineValuesScheduler: RunOnceScheduler;
private hoverRange: Range;
private breakpointHintDecoration: string[];
private breakpointWidget: BreakpointWidget;
private breakpointWidgetVisible: IContextKey<boolean>;
private wordToLineNumbersMap: Map<string, Position[]>;
private exceptionWidget: ExceptionWidget;
private configurationWidget: FloatingClickWidget;
constructor(
private editor: ICodeEditor,
@IDebugService private debugService: IDebugService,
@IContextMenuService private contextMenuService: IContextMenuService,
@IInstantiationService private instantiationService: IInstantiationService,
@IContextKeyService contextKeyService: IContextKeyService,
@ICommandService private commandService: ICommandService,
@ICodeEditorService private codeEditorService: ICodeEditorService,
@ITelemetryService private telemetryService: ITelemetryService,
@IListService listService: IListService,
@IConfigurationService private configurationService: IConfigurationService,
@IThemeService themeService: IThemeService
) {
this.breakpointHintDecoration = [];
this.hoverWidget = new DebugHoverWidget(this.editor, this.debugService, listService, this.instantiationService, themeService);
this.toDispose = [];
this.showHoverScheduler = new RunOnceScheduler(() => this.showHover(this.hoverRange, false), HOVER_DELAY);
this.hideHoverScheduler = new RunOnceScheduler(() => this.hoverWidget.hide(), HOVER_DELAY);
this.removeInlineValuesScheduler = new RunOnceScheduler(() => this.editor.removeDecorations(INLINE_VALUE_DECORATION_KEY), REMOVE_INLINE_VALUES_DELAY);
this.registerListeners();
this.breakpointWidgetVisible = CONTEXT_BREAKPOINT_WIDGET_VISIBLE.bindTo(contextKeyService);
this.updateConfigurationWidgetVisibility();
this.codeEditorService.registerDecorationType(INLINE_VALUE_DECORATION_KEY, {});
this.toggleExceptionWidget();
}
private getContextMenuActions(breakpoints: IBreakpoint[], uri: uri, lineNumber: number): TPromise<(IAction | ContextSubMenu)[]> {
const actions: (IAction | ContextSubMenu)[] = [];
if (breakpoints.length === 1) {
actions.push(this.instantiationService.createInstance(RemoveBreakpointAction, RemoveBreakpointAction.ID, RemoveBreakpointAction.LABEL));
actions.push(this.instantiationService.createInstance(EditConditionalBreakpointAction, EditConditionalBreakpointAction.ID, EditConditionalBreakpointAction.LABEL, this.editor));
if (breakpoints[0].enabled) {
actions.push(this.instantiationService.createInstance(DisableBreakpointAction, DisableBreakpointAction.ID, DisableBreakpointAction.LABEL));
} else {
actions.push(this.instantiationService.createInstance(EnableBreakpointAction, EnableBreakpointAction.ID, EnableBreakpointAction.LABEL));
}
} else if (breakpoints.length > 1) {
const sorted = breakpoints.sort((first, second) => first.column - second.column);
actions.push(new ContextSubMenu(nls.localize('removeBreakpoints', "Remove Breakpoints"), sorted.map(bp => new Action(
'removeColumnBreakpoint',
bp.column ? nls.localize('removeBreakpointOnColumn', "Remove Breakpoint on Column {0}", bp.column) : nls.localize('removeLineBreakpoint', "Remove Line Breakpoint"),
null,
true,
() => this.debugService.removeBreakpoints(bp.getId())
))));
actions.push(new ContextSubMenu(nls.localize('editBreakpoints', "Edit Breakpoints"), sorted.map(bp =>
new Action('editBreakpoint',
bp.column ? nls.localize('editBreakpointOnColumn', "Edit Breakpoint on Column {0}", bp.column) : nls.localize('editLineBrekapoint', "Edit Line Breakpoint"),
null,
true,
() => TPromise.as(this.editor.getContribution<IDebugEditorContribution>(EDITOR_CONTRIBUTION_ID).showBreakpointWidget(bp.lineNumber, bp.column))
)
)));
actions.push(new ContextSubMenu(nls.localize('enableDisableBreakpoints', "Enable/Disable Breakpoints"), sorted.map(bp => new Action(
bp.enabled ? 'disableColumnBreakpoint' : 'enableColumnBreakpoint',
bp.enabled ? (bp.column ? nls.localize('disableColumnBreakpoint', "Disable Breakpoint on Column {0}", bp.column) : nls.localize('disableBreakpointOnLine', "Disable Line Breakpoint"))
: (bp.column ? nls.localize('enableBreakpoints', "Enable Breakpoint on Column {0}", bp.column) : nls.localize('enableBreakpointOnLine', "Enable Line Breakpoint")),
null,
true,
() => this.debugService.enableOrDisableBreakpoints(!bp.enabled, bp)
))));
} else {
actions.push(new Action(
'addBreakpoint',
nls.localize('addBreakpoint', "Add Breakpoint"),
null,
true,
() => this.debugService.addBreakpoints(uri, [{ lineNumber }])
));
actions.push(this.instantiationService.createInstance(AddConditionalBreakpointAction, AddConditionalBreakpointAction.ID, AddConditionalBreakpointAction.LABEL, this.editor, lineNumber));
}
return TPromise.as(actions);
}
private registerListeners(): void {
this.toDispose.push(this.editor.onMouseDown((e: IEditorMouseEvent) => {
if (e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN || /* after last line */ e.target.detail || !this.marginFreeFromNonDebugDecorations(e.target.position.lineNumber)) {
return;
}
const canSetBreakpoints = this.debugService.getConfigurationManager().canSetBreakpointsIn(this.editor.getModel());
const lineNumber = e.target.position.lineNumber;
const uri = this.editor.getModel().uri;
if (e.event.rightButton || (env.isMacintosh && e.event.leftButton && e.event.ctrlKey)) {
if (!canSetBreakpoints) {
return;
}
const anchor = { x: e.event.posx + 1, y: e.event.posy };
const breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp.lineNumber === lineNumber && bp.uri.toString() === uri.toString());
this.contextMenuService.showContextMenu({
getAnchor: () => anchor,
getActions: () => this.getContextMenuActions(breakpoints, uri, lineNumber),
getActionsContext: () => breakpoints.length ? breakpoints[0] : undefined
});
} else {
const breakpoints = this.debugService.getModel().getBreakpoints()
.filter(bp => bp.uri.toString() === uri.toString() && bp.lineNumber === lineNumber);
if (breakpoints.length) {
breakpoints.forEach(bp => this.debugService.removeBreakpoints(bp.getId()));
} else if (canSetBreakpoints) {
this.debugService.addBreakpoints(uri, [{ lineNumber }]);
}
}
}));
this.toDispose.push(this.editor.onMouseMove((e: IEditorMouseEvent) => {
let showBreakpointHintAtLineNumber = -1;
if (e.target.type === MouseTargetType.GUTTER_GLYPH_MARGIN && this.debugService.getConfigurationManager().canSetBreakpointsIn(this.editor.getModel()) &&
this.marginFreeFromNonDebugDecorations(e.target.position.lineNumber)) {
if (!e.target.detail) {
// is not after last line
showBreakpointHintAtLineNumber = e.target.position.lineNumber;
}
}
this.ensureBreakpointHintDecoration(showBreakpointHintAtLineNumber);
}));
this.toDispose.push(this.editor.onMouseLeave((e: IEditorMouseEvent) => {
this.ensureBreakpointHintDecoration(-1);
}));
this.toDispose.push(this.debugService.getViewModel().onDidFocusStackFrame(e => this.onFocusStackFrame(e.stackFrame)));
// hover listeners & hover widget
this.toDispose.push(this.editor.onMouseDown((e: IEditorMouseEvent) => this.onEditorMouseDown(e)));
this.toDispose.push(this.editor.onMouseMove((e: IEditorMouseEvent) => this.onEditorMouseMove(e)));
this.toDispose.push(this.editor.onMouseLeave((e: IEditorMouseEvent) => {
const rect = this.hoverWidget.getDomNode().getBoundingClientRect();
// Only hide the hover widget if the editor mouse leave event is outside the hover widget #3528
if (e.event.posx < rect.left || e.event.posx > rect.right || e.event.posy < rect.top || e.event.posy > rect.bottom) {
this.hideHoverWidget();
}
}));
this.toDispose.push(this.editor.onKeyDown((e: IKeyboardEvent) => this.onKeyDown(e)));
this.toDispose.push(this.editor.onDidChangeModelContent(() => {
this.wordToLineNumbersMap = null;
}));
this.toDispose.push(this.editor.onDidChangeModel(() => {
const sf = this.debugService.getViewModel().focusedStackFrame;
const model = this.editor.getModel();
this.editor.updateOptions({ hover: !sf || !model || model.uri.toString() !== sf.source.uri.toString() });
this.closeBreakpointWidget();
this.toggleExceptionWidget();
this.hideHoverWidget();
this.updateConfigurationWidgetVisibility();
this.wordToLineNumbersMap = null;
this.updateInlineDecorations(sf);
}));
this.toDispose.push(this.editor.onDidScrollChange(() => this.hideHoverWidget));
this.toDispose.push(this.debugService.onDidChangeState((state: State) => {
if (state !== State.Stopped) {
this.toggleExceptionWidget();
}
}));
}
public getId(): string {
return EDITOR_CONTRIBUTION_ID;
}
public showHover(range: Range, focus: boolean): TPromise<void> {
const sf = this.debugService.getViewModel().focusedStackFrame;
const model = this.editor.getModel();
if (sf && model && sf.source.uri.toString() === model.uri.toString()) {
return this.hoverWidget.showAt(range, focus);
}
return undefined;
}
private marginFreeFromNonDebugDecorations(line: number): boolean {
const decorations = this.editor.getLineDecorations(line);
if (decorations) {
for (const { options } of decorations) {
if (options.glyphMarginClassName && options.glyphMarginClassName.indexOf('debug') === -1) {
return false;
}
}
}
return true;
}
private ensureBreakpointHintDecoration(showBreakpointHintAtLineNumber: number): void {
const newDecoration: IModelDeltaDecoration[] = [];
if (showBreakpointHintAtLineNumber !== -1) {
newDecoration.push({
options: DebugEditorContribution.BREAKPOINT_HELPER_DECORATION,
range: {
startLineNumber: showBreakpointHintAtLineNumber,
startColumn: 1,
endLineNumber: showBreakpointHintAtLineNumber,
endColumn: 1
}
});
}
this.breakpointHintDecoration = this.editor.deltaDecorations(this.breakpointHintDecoration, newDecoration);
}
private onFocusStackFrame(sf: IStackFrame): void {
const model = this.editor.getModel();
if (model && sf && sf.source.uri.toString() === model.uri.toString()) {
this.editor.updateOptions({ hover: false });
this.toggleExceptionWidget();
} else {
this.editor.updateOptions({ hover: true });
this.hideHoverWidget();
}
this.updateInlineDecorations(sf);
}
private hideHoverWidget(): void {
if (!this.hideHoverScheduler.isScheduled() && this.hoverWidget.isVisible()) {
this.hideHoverScheduler.schedule();
}
this.showHoverScheduler.cancel();
}
// hover business
private onEditorMouseDown(mouseEvent: IEditorMouseEvent): void {
if (mouseEvent.target.type === MouseTargetType.CONTENT_WIDGET && mouseEvent.target.detail === DebugHoverWidget.ID) {
return;
}
this.hideHoverWidget();
}
private onEditorMouseMove(mouseEvent: IEditorMouseEvent): void {
if (this.debugService.state !== State.Stopped) {
return;
}
const targetType = mouseEvent.target.type;
const stopKey = env.isMacintosh ? 'metaKey' : 'ctrlKey';
if (targetType === MouseTargetType.CONTENT_WIDGET && mouseEvent.target.detail === DebugHoverWidget.ID && !(<any>mouseEvent.event)[stopKey]) {
// mouse moved on top of debug hover widget
return;
}
if (targetType === MouseTargetType.CONTENT_TEXT) {
if (!mouseEvent.target.range.equalsRange(this.hoverRange)) {
this.hoverRange = mouseEvent.target.range;
this.showHoverScheduler.schedule();
}
} else {
this.hideHoverWidget();
}
}
private onKeyDown(e: IKeyboardEvent): void {
const stopKey = env.isMacintosh ? KeyCode.Meta : KeyCode.Ctrl;
if (e.keyCode !== stopKey) {
// do not hide hover when Ctrl/Meta is pressed
this.hideHoverWidget();
}
}
// end hover business
// breakpoint widget
public showBreakpointWidget(lineNumber: number, column: number): void {
if (this.breakpointWidget) {
this.breakpointWidget.dispose();
}
this.breakpointWidget = this.instantiationService.createInstance(BreakpointWidget, this.editor, lineNumber, column);
this.breakpointWidget.show({ lineNumber, column: 1 }, 2);
this.breakpointWidgetVisible.set(true);
}
public closeBreakpointWidget(): void {
if (this.breakpointWidget) {
this.breakpointWidget.dispose();
this.breakpointWidget = null;
this.breakpointWidgetVisible.reset();
this.editor.focus();
}
}
// exception widget
private toggleExceptionWidget(): void {
// Toggles exception widget based on the state of the current editor model and debug stack frame
const model = this.editor.getModel();
const focusedSf = this.debugService.getViewModel().focusedStackFrame;
const callStack = focusedSf ? focusedSf.thread.getCallStack() : null;
if (!model || !focusedSf || !callStack || callStack.length === 0) {
this.closeExceptionWidget();
return;
}
// First call stack frame that is available is the frame where exception has been thrown
const exceptionSf = first(callStack, sf => sf.source && sf.source.available, undefined);
if (!exceptionSf) {
this.closeExceptionWidget();
return;
}
const sameUri = exceptionSf.source.uri.toString() === model.uri.toString();
if (this.exceptionWidget && !sameUri) {
this.closeExceptionWidget();
} else if (sameUri) {
focusedSf.thread.exceptionInfo.then(exceptionInfo => {
if (exceptionInfo && exceptionSf.range.startLineNumber && exceptionSf.range.startColumn) {
this.showExceptionWidget(exceptionInfo, exceptionSf.range.startLineNumber, exceptionSf.range.startColumn);
}
});
}
}
private showExceptionWidget(exceptionInfo: IExceptionInfo, lineNumber: number, column: number): void {
if (this.exceptionWidget) {
this.exceptionWidget.dispose();
}
this.exceptionWidget = this.instantiationService.createInstance(ExceptionWidget, this.editor, exceptionInfo, lineNumber);
this.exceptionWidget.show({ lineNumber, column }, 0);
}
private closeExceptionWidget(): void {
if (this.exceptionWidget) {
this.exceptionWidget.dispose();
this.exceptionWidget = null;
}
}
// configuration widget
private updateConfigurationWidgetVisibility(): void {
const model = this.editor.getModel();
if (model && LAUNCH_JSON_REGEX.test(model.uri.toString())) {
this.configurationWidget = this.instantiationService.createInstance(FloatingClickWidget, this.editor, nls.localize('addConfiguration', "Add Configuration..."), null);
this.configurationWidget.render();
this.toDispose.push(this.configurationWidget.onClick(() => this.addLaunchConfiguration().done(undefined, errors.onUnexpectedError)));
} else if (this.configurationWidget) {
this.configurationWidget.dispose();
}
}
public addLaunchConfiguration(): TPromise<any> {
this.telemetryService.publicLog('debug/addLaunchConfiguration');
let configurationsArrayPosition: Position;
const model = this.editor.getModel();
let depthInArray = 0;
let lastProperty: string;
visit(model.getValue(), {
onObjectProperty: (property, offset, length) => {
lastProperty = property;
},
onArrayBegin: (offset: number, length: number) => {
if (lastProperty === 'configurations' && depthInArray === 0) {
configurationsArrayPosition = model.getPositionAt(offset + 1);
}
depthInArray++;
},
onArrayEnd: () => {
depthInArray--;
}
});
this.editor.focus();
if (!configurationsArrayPosition) {
return this.commandService.executeCommand('editor.action.triggerSuggest');
}
const insertLine = (position: Position): TPromise<any> => {
// Check if there are more characters on a line after a "configurations": [, if yes enter a newline
if (this.editor.getModel().getLineLastNonWhitespaceColumn(position.lineNumber) > position.column) {
this.editor.setPosition(position);
CoreEditingCommands.LineBreakInsert.runEditorCommand(null, this.editor, null);
}
// Check if there is already an empty line to insert suggest, if yes just place the cursor
if (this.editor.getModel().getLineLastNonWhitespaceColumn(position.lineNumber + 1) === 0) {
this.editor.setPosition({ lineNumber: position.lineNumber + 1, column: Constants.MAX_SAFE_SMALL_INTEGER });
return TPromise.as(null);
}
this.editor.setPosition(position);
return this.commandService.executeCommand('editor.action.insertLineAfter');
};
return insertLine(configurationsArrayPosition).then(() => this.commandService.executeCommand('editor.action.triggerSuggest'));
}
private static BREAKPOINT_HELPER_DECORATION: IModelDecorationOptions = {
glyphMarginClassName: 'debug-breakpoint-hint-glyph',
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
};
// Inline Decorations
private updateInlineDecorations(stackFrame: IStackFrame): void {
const model = this.editor.getModel();
if (!this.configurationService.getConfiguration<IDebugConfiguration>('debug').inlineValues ||
!model || !stackFrame || model.uri.toString() !== stackFrame.source.uri.toString()) {
if (!this.removeInlineValuesScheduler.isScheduled()) {
this.removeInlineValuesScheduler.schedule();
}
return;
}
this.removeInlineValuesScheduler.cancel();
stackFrame.getMostSpecificScopes(stackFrame.range)
// Get all top level children in the scope chain
.then(scopes => TPromise.join(scopes.map(scope => scope.getChildren()
.then(children => {
let range = new Range(0, 0, stackFrame.range.startLineNumber, stackFrame.range.startColumn);
if (scope.range) {
range = range.setStartPosition(scope.range.startLineNumber, scope.range.startColumn);
}
return this.createInlineValueDecorationsInsideRange(children, range);
}))).then(decorationsPerScope => {
const allDecorations = decorationsPerScope.reduce((previous, current) => previous.concat(current), []);
this.editor.setDecorations(INLINE_VALUE_DECORATION_KEY, allDecorations);
}));
}
private createInlineValueDecorationsInsideRange(expressions: IExpression[], range: Range): IDecorationOptions[] {
const nameValueMap = new Map<string, string>();
for (let expr of expressions) {
nameValueMap.set(expr.name, expr.value);
// Limit the size of map. Too large can have a perf impact
if (nameValueMap.size >= MAX_NUM_INLINE_VALUES) {
break;
}
}
const lineToNamesMap: Map<number, string[]> = new Map<number, string[]>();
const wordToPositionsMap = this.getWordToPositionsMap();
// Compute unique set of names on each line
nameValueMap.forEach((value, name) => {
if (wordToPositionsMap.has(name)) {
for (let position of wordToPositionsMap.get(name)) {
if (range.containsPosition(position)) {
if (!lineToNamesMap.has(position.lineNumber)) {
lineToNamesMap.set(position.lineNumber, []);
}
if (lineToNamesMap.get(position.lineNumber).indexOf(name) === -1) {
lineToNamesMap.get(position.lineNumber).push(name);
}
}
}
}
});
const decorations: IDecorationOptions[] = [];
// Compute decorators for each line
lineToNamesMap.forEach((names, line) => {
const contentText = names.sort((first, second) => {
const content = this.editor.getModel().getLineContent(line);
return content.indexOf(first) - content.indexOf(second);
}).map(name => `${name} = ${nameValueMap.get(name)}`).join(', ');
decorations.push(this.createInlineValueDecoration(line, contentText));
});
return decorations;
}
private createInlineValueDecoration(lineNumber: number, contentText: string): IDecorationOptions {
// If decoratorText is too long, trim and add ellipses. This could happen for minified files with everything on a single line
if (contentText.length > MAX_INLINE_DECORATOR_LENGTH) {
contentText = contentText.substr(0, MAX_INLINE_DECORATOR_LENGTH) + '...';
}
return {
range: {
startLineNumber: lineNumber,
endLineNumber: lineNumber,
startColumn: Constants.MAX_SAFE_SMALL_INTEGER,
endColumn: Constants.MAX_SAFE_SMALL_INTEGER
},
renderOptions: {
after: {
contentText,
backgroundColor: 'rgba(255, 200, 0, 0.2)',
margin: '10px'
},
dark: {
after: {
color: 'rgba(255, 255, 255, 0.5)',
}
},
light: {
after: {
color: 'rgba(0, 0, 0, 0.5)',
}
}
}
};
}
private getWordToPositionsMap(): Map<string, Position[]> {
if (!this.wordToLineNumbersMap) {
this.wordToLineNumbersMap = new Map<string, Position[]>();
const model = this.editor.getModel();
// For every word in every line, map its ranges for fast lookup
for (let lineNumber = 1, len = model.getLineCount(); lineNumber <= len; ++lineNumber) {
const lineContent = model.getLineContent(lineNumber);
// If line is too long then skip the line
if (lineContent.length > MAX_TOKENIZATION_LINE_LEN) {
continue;
}
model.forceTokenization(lineNumber);
const lineTokens = model.getLineTokens(lineNumber);
for (let token = lineTokens.firstToken(); !!token; token = token.next()) {
const tokenStr = lineContent.substring(token.startOffset, token.endOffset);
// Token is a word and not a comment
if (token.tokenType === StandardTokenType.Other) {
DEFAULT_WORD_REGEXP.lastIndex = 0; // We assume tokens will usually map 1:1 to words if they match
const wordMatch = DEFAULT_WORD_REGEXP.exec(tokenStr);
if (wordMatch) {
const word = wordMatch[0];
if (!this.wordToLineNumbersMap.has(word)) {
this.wordToLineNumbersMap.set(word, []);
}
this.wordToLineNumbersMap.get(word).push(new Position(lineNumber, token.startOffset));
}
}
}
}
}
return this.wordToLineNumbersMap;
}
public dispose(): void {
if (this.breakpointWidget) {
this.breakpointWidget.dispose();
}
if (this.hoverWidget) {
this.hoverWidget.dispose();
}
if (this.configurationWidget) {
this.configurationWidget.dispose();
}
this.toDispose = lifecycle.dispose(this.toDispose);
}
}

Some files were not shown because too many files have changed in this diff Show More