Archived
Merge branch 'ads-main-vscode-2020-07-15T23-51-12' into main
This commit is contained in:
Vendored
+17
-33
@@ -22,8 +22,6 @@
|
||||
}
|
||||
}(this, function () {
|
||||
const path = require.__$__nodeRequire('path');
|
||||
const webFrame = require.__$__nodeRequire('electron').webFrame;
|
||||
const ipc = require.__$__nodeRequire('electron').ipcRenderer;
|
||||
const bootstrap = globalThis.MonacoBootstrap;
|
||||
|
||||
/**
|
||||
@@ -36,7 +34,6 @@
|
||||
/**
|
||||
* // configuration: INativeWindowConfiguration
|
||||
* @type {{
|
||||
* zoomLevel?: number,
|
||||
* extensionDevelopmentPath?: string[],
|
||||
* extensionTestsPath?: string,
|
||||
* userEnv?: { [key: string]: string | undefined },
|
||||
@@ -45,12 +42,6 @@
|
||||
* }} */
|
||||
const configuration = JSON.parse(args['config'] || '{}') || {};
|
||||
|
||||
// Apply zoom level early to avoid glitches
|
||||
const zoomLevel = configuration.zoomLevel;
|
||||
if (typeof zoomLevel === 'number' && zoomLevel !== 0) {
|
||||
webFrame.setZoomLevel(zoomLevel);
|
||||
}
|
||||
|
||||
// Error handler
|
||||
process.on('uncaughtException', function (error) {
|
||||
onUnexpectedError(error, enableDeveloperTools);
|
||||
@@ -96,28 +87,9 @@
|
||||
const loaderConfig = {
|
||||
baseUrl: `${bootstrap.uriFromPath(configuration.appRoot)}/out`,
|
||||
'vs/nls': nlsConfig,
|
||||
nodeModules: [/*BUILD->INSERT_NODE_MODULES*/]
|
||||
amdModulesPattern: /^(vs|sql)\//, // {{SQL CARBON EDIT}} include sql in regex
|
||||
};
|
||||
|
||||
loaderConfig.nodeModules = loaderConfig.nodeModules.concat([
|
||||
'@angular/common',
|
||||
'@angular/core',
|
||||
'@angular/forms',
|
||||
'@angular/platform-browser',
|
||||
'@angular/platform-browser-dynamic',
|
||||
'@angular/router',
|
||||
'rxjs/Observable',
|
||||
'rxjs/add/observable/fromPromise',
|
||||
'rxjs/Subject',
|
||||
'rxjs/Observer',
|
||||
'slickgrid/lib/jquery.event.drag-2.3.0',
|
||||
'slickgrid/lib/jquery-ui-1.9.2',
|
||||
'slickgrid/slick.core',
|
||||
'slickgrid/slick.grid',
|
||||
'slickgrid/slick.editors',
|
||||
'slickgrid/slick.dataview'
|
||||
]);
|
||||
|
||||
// cached data config
|
||||
if (configuration.nodeCachedDataDir) {
|
||||
loaderConfig.nodeCachedData = {
|
||||
@@ -178,6 +150,8 @@
|
||||
* @returns {() => void}
|
||||
*/
|
||||
function registerDeveloperKeybindings(disallowReloadKeybinding) {
|
||||
const ipcRenderer = globals().ipcRenderer;
|
||||
|
||||
const extractKey = function (e) {
|
||||
return [
|
||||
e.ctrlKey ? 'ctrl-' : '',
|
||||
@@ -196,9 +170,9 @@
|
||||
let listener = function (e) {
|
||||
const key = extractKey(e);
|
||||
if (key === TOGGLE_DEV_TOOLS_KB || key === TOGGLE_DEV_TOOLS_KB_ALT) {
|
||||
ipc.send('vscode:toggleDevTools');
|
||||
ipcRenderer.send('vscode:toggleDevTools');
|
||||
} else if (key === RELOAD_KB && !disallowReloadKeybinding) {
|
||||
ipc.send('vscode:reloadWindow');
|
||||
ipcRenderer.send('vscode:reloadWindow');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -218,7 +192,8 @@
|
||||
*/
|
||||
function onUnexpectedError(error, enableDeveloperTools) {
|
||||
if (enableDeveloperTools) {
|
||||
ipc.send('vscode:openDevTools');
|
||||
const ipcRenderer = globals().ipcRenderer;
|
||||
ipcRenderer.send('vscode:openDevTools');
|
||||
}
|
||||
|
||||
console.error(`[uncaught exception]: ${error}`);
|
||||
@@ -228,7 +203,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {typeof import('./vs/base/parts/sandbox/electron-sandbox/globals')}
|
||||
*/
|
||||
function globals() {
|
||||
// @ts-ignore (defined in globals.js)
|
||||
return window.vscode;
|
||||
}
|
||||
|
||||
return {
|
||||
load
|
||||
load,
|
||||
globals
|
||||
};
|
||||
}));
|
||||
|
||||
@@ -206,6 +206,8 @@ function configureCommandlineSwitchesSync(cliArgs) {
|
||||
];
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
|
||||
// Force enable screen readers on Linux via this flag
|
||||
SUPPORTED_ELECTRON_SWITCHES.push('force-renderer-accessibility');
|
||||
}
|
||||
|
||||
@@ -223,6 +225,7 @@ function configureCommandlineSwitchesSync(cliArgs) {
|
||||
|
||||
// Append Electron flags to Electron
|
||||
if (SUPPORTED_ELECTRON_SWITCHES.indexOf(argvKey) !== -1) {
|
||||
|
||||
// Color profile
|
||||
if (argvKey === 'force-color-profile') {
|
||||
if (argvValue) {
|
||||
|
||||
@@ -14,7 +14,6 @@ import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import * as map from 'vs/base/common/map';
|
||||
import { firstIndex } from 'vs/base/common/arrays';
|
||||
|
||||
export interface ITabbedPanelStyles {
|
||||
@@ -285,7 +284,7 @@ export class TabbedPanel extends Disposable {
|
||||
}
|
||||
}
|
||||
if (!this._shownTabId && this._tabMap.size > 0) {
|
||||
this.showTab(map.values(this._tabMap)[0].tab.identifier);
|
||||
this.showTab(this._tabMap.values().next().value.tab.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/t
|
||||
import { UNSAVED_GROUP_ID, mssqlProviderName } from 'sql/platform/connection/common/constants';
|
||||
import { $ } from 'vs/base/browser/dom';
|
||||
import { OEManageConnectionAction } from 'sql/workbench/contrib/dashboard/browser/dashboardActions';
|
||||
import { IViewsService, IView, ViewContainerLocation, ViewContainer } from 'vs/workbench/common/views';
|
||||
import { IViewsService, IView, ViewContainerLocation, ViewContainer, IViewPaneContainer } from 'vs/workbench/common/views';
|
||||
import { ConsoleLogService } from 'vs/platform/log/common/log';
|
||||
import { IProgressIndicator } from 'vs/platform/progress/common/progress';
|
||||
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
|
||||
@@ -111,6 +111,9 @@ suite('SQL Connection Tree Action tests', () => {
|
||||
});
|
||||
|
||||
const viewsService = new class implements IViewsService {
|
||||
getActiveViewPaneContainerWithId(viewContainerId: string): IViewPaneContainer {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getViewProgressIndicator(id: string): IProgressIndicator {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { SplitView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { values } from 'vs/base/common/map';
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
@@ -44,6 +43,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { Iterable } from 'vs/base/common/iterator';
|
||||
|
||||
export const VIEWLET_ID = 'workbench.view.accountpanel';
|
||||
|
||||
@@ -219,7 +219,7 @@ export class AccountDialog extends Modal {
|
||||
this._addAccountButton.label = localize('accountDialog.addConnection', "Add an account");
|
||||
|
||||
this._register(this._addAccountButton.onDidClick(async () => {
|
||||
const vals = values(this._providerViewsMap);
|
||||
const vals = Iterable.consume(this._providerViewsMap.values())[0];
|
||||
|
||||
let pickedValue: string;
|
||||
if (vals.length === 0) {
|
||||
@@ -291,8 +291,8 @@ export class AccountDialog extends Modal {
|
||||
private showSplitView() {
|
||||
this._splitViewContainer.hidden = false;
|
||||
this._noaccountViewContainer.hidden = true;
|
||||
if (values(this._providerViewsMap).length > 0) {
|
||||
const firstView = values(this._providerViewsMap)[0];
|
||||
if (Iterable.consume(this._providerViewsMap.values()).length > 0) {
|
||||
const firstView = this._providerViewsMap.values().next().value;
|
||||
if (firstView instanceof AccountPanel) {
|
||||
firstView.setSelection([0]);
|
||||
firstView.focus();
|
||||
@@ -301,7 +301,7 @@ export class AccountDialog extends Modal {
|
||||
}
|
||||
|
||||
private isEmptyLinkedAccount(): boolean {
|
||||
for (const provider of values(this._providerViewsMap)) {
|
||||
for (const provider of this._providerViewsMap.values()) {
|
||||
const listView = provider.view;
|
||||
if (listView && listView.length > 0) {
|
||||
return false;
|
||||
@@ -312,7 +312,7 @@ export class AccountDialog extends Modal {
|
||||
|
||||
public dispose(): void {
|
||||
super.dispose();
|
||||
for (const provider of values(this._providerViewsMap)) {
|
||||
for (const provider of this._providerViewsMap.values()) {
|
||||
if (provider.addAccountAction) {
|
||||
provider.addAccountAction.dispose();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { IInstantiationService, _util, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { Trace } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { values } from 'vs/base/common/map';
|
||||
import { IModuleFactory, IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
@@ -16,7 +15,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
const selectorCounter = new Map<string, number>();
|
||||
|
||||
export function providerIterator(service: IInstantiationService): Provider[] {
|
||||
return Array.from(values(_util.serviceIds)).map(v => {
|
||||
return Array.from(_util.serviceIds.values()).map(v => {
|
||||
let factory = () => {
|
||||
return (<any>service)._getOrCreateServiceInstance(v, Trace.traceCreation(v));
|
||||
};
|
||||
|
||||
@@ -22,7 +22,6 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
||||
import { uriPrefixes } from 'sql/platform/connection/common/utils';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { getErrorMessage } from 'vs/base/common/errors';
|
||||
import { find, firstIndex } from 'vs/base/common/arrays';
|
||||
@@ -213,7 +212,7 @@ export class NotebookModel extends Disposable implements INotebookModel {
|
||||
}
|
||||
|
||||
public standardKernelsDisplayName(): string[] {
|
||||
return Array.from(keys(this._kernelDisplayNameToNotebookProviderIds));
|
||||
return Array.from(this._kernelDisplayNameToNotebookProviderIds.keys());
|
||||
}
|
||||
|
||||
public get inErrorState(): boolean {
|
||||
|
||||
@@ -27,7 +27,6 @@ import { IQueryManagementService } from 'sql/workbench/services/query/common/que
|
||||
import { ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { SqlNotebookProvider } from 'sql/workbench/services/notebook/browser/sql/sqlNotebookProvider';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
import { IFileService, IFileStatWithMetadata } from 'vs/platform/files/common/files';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
@@ -269,7 +268,7 @@ export class NotebookService extends Disposable implements INotebookService {
|
||||
}
|
||||
|
||||
getSupportedFileExtensions(): string[] {
|
||||
return Array.from(keys(this._fileToProviders));
|
||||
return Array.from(this._fileToProviders.keys());
|
||||
}
|
||||
|
||||
getProvidersForFileType(fileType: string): string[] {
|
||||
|
||||
@@ -102,7 +102,7 @@ export async function getResultsString(provider: IGridDataProvider, selection: S
|
||||
|
||||
let copyString = '';
|
||||
if (includeHeaders) {
|
||||
copyString = [...headers.values()].join('\t').concat(eol);
|
||||
copyString = Array.from(headers.values()).join('\t').concat(eol);
|
||||
}
|
||||
|
||||
const rowKeys = [...headers.keys()];
|
||||
|
||||
@@ -10,7 +10,6 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import * as azdata from 'azdata';
|
||||
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { IAdsTelemetryService, ITelemetryEventProperties } from 'sql/platform/telemetry/common/telemetry';
|
||||
import EditQueryRunner from 'sql/workbench/services/editData/common/editQueryRunner';
|
||||
@@ -175,7 +174,7 @@ export class QueryManagementService implements IQueryManagementService {
|
||||
}
|
||||
|
||||
public getRegisteredProviders(): string[] {
|
||||
return Array.from(keys(this._requestHandlers));
|
||||
return Array.from(this._requestHandlers.keys());
|
||||
}
|
||||
|
||||
private addTelemetry(eventName: string, ownerUri: string, runOptions?: ExecutionPlanOptions): void {
|
||||
|
||||
@@ -221,10 +221,13 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
||||
allowedSchemes.push(Schemas.command);
|
||||
}
|
||||
|
||||
// values that are too long will freeze the UI
|
||||
let value = markdown.value ?? '';
|
||||
if (value.length > 100_000) {
|
||||
value = `${value.substr(0, 100_000)}…`;
|
||||
}
|
||||
const renderedMarkdown = marked.parse(
|
||||
markdown.supportThemeIcons
|
||||
? markdownEscapeEscapedCodicons(markdown.value || '')
|
||||
: (markdown.value || ''),
|
||||
markdown.supportThemeIcons ? markdownEscapeEscapedCodicons(value) : value,
|
||||
markedOptions
|
||||
);
|
||||
|
||||
|
||||
@@ -406,6 +406,7 @@ export interface IActionBarOptions {
|
||||
animated?: boolean;
|
||||
triggerKeys?: ActionTrigger;
|
||||
allowContextMenu?: boolean;
|
||||
preventLoopNavigation?: boolean;
|
||||
}
|
||||
|
||||
const defaultOptions: IActionBarOptions = {
|
||||
@@ -509,9 +510,9 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
let eventHandled = true;
|
||||
|
||||
if (event.equals(previousKey)) {
|
||||
this.focusPrevious();
|
||||
eventHandled = this.focusPrevious();
|
||||
} else if (event.equals(nextKey)) {
|
||||
this.focusNext();
|
||||
eventHandled = this.focusNext();
|
||||
} else if (event.equals(KeyCode.Escape)) {
|
||||
this._onDidCancel.fire();
|
||||
} else if (this.isTriggerKeyEvent(event)) {
|
||||
@@ -724,7 +725,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
|
||||
if (selectFirst && typeof this.focusedItem === 'undefined') {
|
||||
// Focus the first enabled item
|
||||
this.focusedItem = this.viewItems.length - 1;
|
||||
this.focusedItem = -1;
|
||||
this.focusNext();
|
||||
} else {
|
||||
if (index !== undefined) {
|
||||
@@ -735,7 +736,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
}
|
||||
|
||||
protected focusNext(): void {
|
||||
protected focusNext(): boolean {
|
||||
if (typeof this.focusedItem === 'undefined') {
|
||||
this.focusedItem = this.viewItems.length - 1;
|
||||
}
|
||||
@@ -744,6 +745,11 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
let item: IActionViewItem;
|
||||
|
||||
do {
|
||||
if (this.options.preventLoopNavigation && this.focusedItem + 1 >= this.viewItems.length) {
|
||||
this.focusedItem = startIndex;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.focusedItem = (this.focusedItem + 1) % this.viewItems.length;
|
||||
item = this.viewItems[this.focusedItem];
|
||||
} while (this.focusedItem !== startIndex && !item.isEnabled());
|
||||
@@ -753,9 +759,10 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
|
||||
this.updateFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected focusPrevious(): void {
|
||||
protected focusPrevious(): boolean {
|
||||
if (typeof this.focusedItem === 'undefined') {
|
||||
this.focusedItem = 0;
|
||||
}
|
||||
@@ -767,6 +774,11 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
this.focusedItem = this.focusedItem - 1;
|
||||
|
||||
if (this.focusedItem < 0) {
|
||||
if (this.options.preventLoopNavigation) {
|
||||
this.focusedItem = startIndex;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.focusedItem = this.viewItems.length - 1;
|
||||
}
|
||||
|
||||
@@ -778,6 +790,7 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
|
||||
this.updateFocus(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected updateFocus(fromRight?: boolean, preventScroll?: boolean): void {
|
||||
|
||||
Binary file not shown.
@@ -162,6 +162,7 @@ export class ContextView extends Disposable {
|
||||
this.view.className = 'context-view';
|
||||
this.view.style.top = '0px';
|
||||
this.view.style.left = '0px';
|
||||
this.view.style.position = this.useFixedPosition ? 'fixed' : 'absolute';
|
||||
DOM.show(this.view);
|
||||
|
||||
// Render content
|
||||
|
||||
@@ -175,8 +175,8 @@ export class InputBox extends Widget {
|
||||
this.input.setAttribute('autocapitalize', 'off');
|
||||
this.input.setAttribute('spellcheck', 'false');
|
||||
|
||||
this.onfocus(this.input, () => dom.addClass(this.element, 'synthetic-focus'));
|
||||
this.onblur(this.input, () => dom.removeClass(this.element, 'synthetic-focus'));
|
||||
this.onfocus(this.input, () => this.element.classList.add('synthetic-focus'));
|
||||
this.onblur(this.input, () => this.element.classList.remove('synthetic-focus'));
|
||||
|
||||
if (this.options.flexibleHeight) {
|
||||
this.maxHeight = typeof this.options.flexibleMaxHeight === 'number' ? this.options.flexibleMaxHeight : Number.POSITIVE_INFINITY;
|
||||
@@ -392,11 +392,11 @@ export class InputBox extends Widget {
|
||||
public showMessage(message: IMessage, force?: boolean): void {
|
||||
this.message = message;
|
||||
|
||||
dom.removeClass(this.element, 'idle');
|
||||
dom.removeClass(this.element, 'info');
|
||||
dom.removeClass(this.element, 'warning');
|
||||
dom.removeClass(this.element, 'error');
|
||||
dom.addClass(this.element, this.classForType(message.type));
|
||||
this.element.classList.remove('idle');
|
||||
this.element.classList.remove('info');
|
||||
this.element.classList.remove('warning');
|
||||
this.element.classList.remove('error');
|
||||
this.element.classList.add(this.classForType(message.type));
|
||||
|
||||
const styles = this.stylesForType(this.message.type);
|
||||
this.element.style.border = styles.border ? `1px solid ${styles.border}` : '';
|
||||
@@ -409,10 +409,10 @@ export class InputBox extends Widget {
|
||||
public hideMessage(): void {
|
||||
this.message = null;
|
||||
|
||||
dom.removeClass(this.element, 'info');
|
||||
dom.removeClass(this.element, 'warning');
|
||||
dom.removeClass(this.element, 'error');
|
||||
dom.addClass(this.element, 'idle');
|
||||
this.element.classList.remove('info');
|
||||
this.element.classList.remove('warning');
|
||||
this.element.classList.remove('error');
|
||||
this.element.classList.add('idle');
|
||||
|
||||
this._hideMessage();
|
||||
this.applyStyles();
|
||||
@@ -494,7 +494,7 @@ export class InputBox extends Widget {
|
||||
const spanElement = (this.message.formatContent
|
||||
? renderFormattedText(this.message.content, renderOptions)
|
||||
: renderText(this.message.content, renderOptions));
|
||||
dom.addClass(spanElement, this.classForType(this.message.type));
|
||||
spanElement.classList.add(this.classForType(this.message.type));
|
||||
|
||||
const styles = this.stylesForType(this.message.type);
|
||||
spanElement.style.backgroundColor = styles.background ? styles.background.toString() : '';
|
||||
@@ -543,7 +543,7 @@ export class InputBox extends Widget {
|
||||
|
||||
this.validate();
|
||||
this.updateMirror();
|
||||
dom.toggleClass(this.input, 'empty', !this.value);
|
||||
this.input.classList.toggle('empty', !this.value);
|
||||
|
||||
if (this.state === 'open' && this.contextViewProvider) {
|
||||
this.contextViewProvider.layout();
|
||||
|
||||
@@ -411,7 +411,6 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
if (this.supportDynamicHeights) {
|
||||
this._rerender(this.lastRenderTop, this.lastRenderHeight);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
splice(start: number, deleteCount: number, elements: T[] = []): T[] {
|
||||
@@ -790,8 +789,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
item.dragStartDisposable.dispose();
|
||||
|
||||
const renderer = this.renderers.get(item.templateId);
|
||||
if (renderer && renderer.disposeElement) {
|
||||
renderer.disposeElement(item.element, index, item.row!.templateData, item.size);
|
||||
if (item.row && renderer && renderer.disposeElement) {
|
||||
renderer.disposeElement(item.element, index, item.row.templateData, item.size);
|
||||
}
|
||||
|
||||
this.cache.release(item.row!);
|
||||
|
||||
@@ -854,6 +854,7 @@ export interface IListOptions<T> {
|
||||
readonly horizontalScrolling?: boolean;
|
||||
readonly additionalScrollHeight?: number;
|
||||
readonly transformOptimization?: boolean;
|
||||
readonly smoothScrolling?: boolean;
|
||||
}
|
||||
|
||||
export interface IListStyles {
|
||||
|
||||
@@ -395,10 +395,9 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
|
||||
}
|
||||
|
||||
this._register(addDisposableListener(this.element, EventType.MOUSE_UP, e => {
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
// removed default prevention as it conflicts
|
||||
// with BaseActionViewItem #101537
|
||||
// add back if issues arise and link new issue
|
||||
EventHelper.stop(e, true);
|
||||
this.onClick(e);
|
||||
}));
|
||||
|
||||
@@ -326,7 +326,15 @@ export class MenuBar extends Disposable {
|
||||
let event = new StandardKeyboardEvent(e as KeyboardEvent);
|
||||
let eventHandled = true;
|
||||
|
||||
if ((event.equals(KeyCode.DownArrow) || event.equals(KeyCode.Enter) || (this.options.compactMode !== undefined && event.equals(KeyCode.Space))) && !this.isOpen) {
|
||||
const triggerKeys = [KeyCode.Enter];
|
||||
if (this.options.compactMode === undefined) {
|
||||
triggerKeys.push(KeyCode.DownArrow);
|
||||
} else {
|
||||
triggerKeys.push(KeyCode.Space);
|
||||
triggerKeys.push(this.options.compactMode === Direction.Right ? KeyCode.RightArrow : KeyCode.LeftArrow);
|
||||
}
|
||||
|
||||
if ((triggerKeys.some(k => event.equals(k)) && !this.isOpen)) {
|
||||
this.focusedMenu = { index: MenuBar.OVERFLOW_INDEX };
|
||||
this.openedViaKeyboard = true;
|
||||
this.focusState = MenubarState.OPEN;
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { INewScrollDimensions, INewScrollPosition, IScrollDimensions, IScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { getZoomFactor } from 'vs/base/browser/browser';
|
||||
|
||||
const HIDE_TIMEOUT = 500;
|
||||
const SCROLL_WHEEL_SENSITIVITY = 50;
|
||||
@@ -130,13 +131,18 @@ export class MouseWheelClassifier {
|
||||
// }
|
||||
}
|
||||
|
||||
if (Math.abs(item.deltaX - Math.round(item.deltaX)) > 0 || Math.abs(item.deltaY - Math.round(item.deltaY)) > 0) {
|
||||
if (!this._isAlmostInt(item.deltaX) || !this._isAlmostInt(item.deltaY)) {
|
||||
// non-integer deltas => indicator that this is not a physical mouse wheel
|
||||
score += 0.25;
|
||||
}
|
||||
|
||||
return Math.min(Math.max(score, 0), 1);
|
||||
}
|
||||
|
||||
private _isAlmostInt(value: number): boolean {
|
||||
const delta = Math.abs(Math.round(value) - value);
|
||||
return (delta < 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractScrollableElement extends Widget {
|
||||
@@ -343,10 +349,11 @@ export abstract class AbstractScrollableElement extends Widget {
|
||||
|
||||
const classifier = MouseWheelClassifier.INSTANCE;
|
||||
if (SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED) {
|
||||
if (platform.isWindows) {
|
||||
// On Windows, the incoming delta events are multiplied with the device pixel ratio,
|
||||
// so to get a better classification, simply undo that.
|
||||
classifier.accept(Date.now(), e.deltaX / window.devicePixelRatio, e.deltaY / window.devicePixelRatio);
|
||||
const osZoomFactor = window.devicePixelRatio / getZoomFactor();
|
||||
if (platform.isWindows || platform.isLinux) {
|
||||
// On Windows and Linux, the incoming delta events are multiplied with the OS zoom factor.
|
||||
// The OS zoom factor can be reverse engineered by using the device pixel ratio and the configured zoom factor into account.
|
||||
classifier.accept(Date.now(), e.deltaX / osZoomFactor, e.deltaY / osZoomFactor);
|
||||
} else {
|
||||
classifier.accept(Date.now(), e.deltaX, e.deltaY);
|
||||
}
|
||||
|
||||
@@ -951,6 +951,7 @@ export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions {
|
||||
readonly filterOnType?: boolean;
|
||||
readonly smoothScrolling?: boolean;
|
||||
readonly horizontalScrolling?: boolean;
|
||||
readonly expandOnlyOnDoubleClick?: boolean;
|
||||
}
|
||||
|
||||
export interface IAbstractTreeOptions<T, TFilterData = void> extends IAbstractTreeOptionsUpdate, IListOptions<T> {
|
||||
@@ -1094,7 +1095,10 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
|
||||
return super.onViewPointer(e);
|
||||
}
|
||||
|
||||
const onTwistie = hasClass(e.browserEvent.target as HTMLElement, 'monaco-tl-twistie');
|
||||
const target = e.browserEvent.target as HTMLElement;
|
||||
const onTwistie = hasClass(target, 'monaco-tl-twistie')
|
||||
|| (hasClass(target, 'monaco-icon-label') && hasClass(target, 'folder-icon') && e.browserEvent.offsetX < 16);
|
||||
|
||||
let expandOnlyOnTwistieClick = false;
|
||||
|
||||
if (typeof this.tree.expandOnlyOnTwistieClick === 'function') {
|
||||
@@ -1107,6 +1111,10 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
|
||||
return super.onViewPointer(e);
|
||||
}
|
||||
|
||||
if (this.tree.expandOnlyOnDoubleClick && e.browserEvent.detail !== 2 && !onTwistie) {
|
||||
return super.onViewPointer(e);
|
||||
}
|
||||
|
||||
if (node.collapsible) {
|
||||
const model = ((this.tree as any).model as ITreeModel<T, TFilterData, TRef>); // internal
|
||||
const location = model.getNodeLocation(node);
|
||||
@@ -1244,6 +1252,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
get filterOnType(): boolean { return !!this._options.filterOnType; }
|
||||
get onDidChangeTypeFilterPattern(): Event<string> { return this.typeFilterController ? this.typeFilterController.onDidChangePattern : Event.None; }
|
||||
|
||||
get expandOnlyOnDoubleClick(): boolean { return this._options.expandOnlyOnDoubleClick ?? false; }
|
||||
get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? false : this._options.expandOnlyOnTwistieClick; }
|
||||
|
||||
private readonly _onDidUpdateOptions = new Emitter<IAbstractTreeOptions<T, TFilterData>>();
|
||||
|
||||
@@ -591,6 +591,14 @@ export function asArray<T>(x: T | T[]): T[] {
|
||||
return Array.isArray(x) ? x : [x];
|
||||
}
|
||||
|
||||
export function toArray<T>(iterable: IterableIterator<T>): T[] {
|
||||
const result: T[] = [];
|
||||
for (let element of iterable) {
|
||||
result.push(element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getRandomElement<T>(arr: T[]): T | undefined {
|
||||
return arr[Math.floor(Math.random() * arr.length)];
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ export class Codicon {
|
||||
_registry.add(this);
|
||||
}
|
||||
public get classNames() { return 'codicon codicon-' + this.id; }
|
||||
// classNamesArray is useful for migrating to ES6 classlist
|
||||
public get classNamesArray() { return ['codicon', 'codicon-' + this.id]; }
|
||||
public get cssSelector() { return '.codicon.codicon-' + this.id; }
|
||||
}
|
||||
|
||||
@@ -472,6 +474,8 @@ export namespace Codicon {
|
||||
export const stopCircle = new Codicon('stop-circle', { character: '\\eba5' });
|
||||
export const playCircle = new Codicon('play-circle', { character: '\\eba6' });
|
||||
export const record = new Codicon('record', { character: '\\eba7' });
|
||||
export const debugAltSmall = new Codicon('debug-alt-small', { character: '\\eba8' });
|
||||
export const vmConnect = new Codicon('vm-connect', { character: '\\eba9' });
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -203,3 +203,12 @@ export class NotImplementedError extends Error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class NotSupportedError extends Error {
|
||||
constructor(message?: string) {
|
||||
super('NotSupported');
|
||||
if (message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +42,7 @@ export function scoreFuzzy(target: string, query: string, queryLower: string, fu
|
||||
// When not searching fuzzy, we require the query to be contained fully
|
||||
// in the target string contiguously.
|
||||
if (!fuzzy) {
|
||||
const indexOfQueryInTarget = targetLower.indexOf(queryLower);
|
||||
if (indexOfQueryInTarget === -1) {
|
||||
if (!targetLower.includes(queryLower)) {
|
||||
// if (DEBUG) {
|
||||
// console.log(`Characters not matching consecutively ${queryLower} within ${targetLower}`);
|
||||
// }
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { equals } from 'vs/base/common/arrays';
|
||||
import { UriComponents } from 'vs/base/common/uri';
|
||||
import { escapeCodicons } from 'vs/base/common/codicons';
|
||||
import { illegalArgument } from 'vs/base/common/errors';
|
||||
|
||||
export interface IMarkdownString {
|
||||
readonly value: string;
|
||||
@@ -22,6 +23,10 @@ export class MarkdownString implements IMarkdownString {
|
||||
private _value: string = '',
|
||||
isTrustedOrOptions: boolean | { isTrusted?: boolean, supportThemeIcons?: boolean } = false,
|
||||
) {
|
||||
if (typeof this._value !== 'string') {
|
||||
throw illegalArgument('value');
|
||||
}
|
||||
|
||||
if (typeof isTrustedOrOptions === 'boolean') {
|
||||
this._isTrusted = isTrustedOrOptions;
|
||||
this._supportThemeIcons = false;
|
||||
@@ -30,7 +35,6 @@ export class MarkdownString implements IMarkdownString {
|
||||
this._isTrusted = isTrustedOrOptions.isTrusted ?? false;
|
||||
this._supportThemeIcons = isTrustedOrOptions.supportThemeIcons ?? false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
get value() { return this._value; }
|
||||
|
||||
@@ -9,27 +9,6 @@ import { compareSubstringIgnoreCase, compare, compareSubstring } from 'vs/base/c
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
|
||||
/**
|
||||
* @deprecated ES6: use `[...SetOrMap.values()]`
|
||||
*/
|
||||
export function values<V = any>(set: Set<V>): V[];
|
||||
export function values<K = any, V = any>(map: Map<K, V>): V[];
|
||||
export function values<V>(forEachable: { forEach(callback: (value: V, ...more: any[]) => any): void }): V[] {
|
||||
const result: V[] = [];
|
||||
forEachable.forEach(value => result.push(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated ES6: use `[...map.keys()]`
|
||||
*/
|
||||
export function keys<K, V>(map: Map<K, V>): K[] {
|
||||
const result: K[] = [];
|
||||
map.forEach((_value, key) => result.push(key));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getOrSet<K, V>(map: Map<K, V>, key: K, value: V): V {
|
||||
let result = map.get(key);
|
||||
if (result === undefined) {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { basename, posix, extname } from 'vs/base/common/path';
|
||||
import { startsWithUTF8BOM } from 'vs/base/common/strings';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { match } from 'vs/base/common/glob';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
@@ -247,34 +246,6 @@ export function isUnspecific(mime: string[] | string): boolean {
|
||||
return mime.length === 1 && isUnspecific(mime[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a suggestion for the filename by the following logic:
|
||||
* 1. If a relevant extension exists and is an actual filename extension (starting with a dot), suggest the prefix appended by the first one.
|
||||
* 2. Otherwise, if there are other extensions, suggest the first one.
|
||||
* 3. Otherwise, suggest the prefix.
|
||||
*/
|
||||
export function suggestFilename(mode: string | undefined, prefix: string): string {
|
||||
const extensions = registeredAssociations
|
||||
.filter(assoc => !assoc.userConfigured && assoc.extension && assoc.id === mode)
|
||||
.map(assoc => assoc.extension);
|
||||
|
||||
const extensionsWithDotFirst = coalesce(extensions)
|
||||
.filter(assoc => assoc.startsWith('.'));
|
||||
|
||||
if (extensionsWithDotFirst.length > 0) {
|
||||
const candidateExtension = extensionsWithDotFirst[0];
|
||||
if (prefix.endsWith(candidateExtension)) {
|
||||
// do not add the prefix if it already exists
|
||||
// https://github.com/microsoft/vscode/issues/83603
|
||||
return prefix;
|
||||
}
|
||||
|
||||
return prefix + candidateExtension;
|
||||
}
|
||||
|
||||
return extensions[0] || prefix;
|
||||
}
|
||||
|
||||
interface MapExtToMediaMimes {
|
||||
[index: string]: string;
|
||||
}
|
||||
|
||||
@@ -9,22 +9,22 @@
|
||||
|
||||
function _factory(sharedObj) {
|
||||
|
||||
sharedObj._performanceEntries = sharedObj._performanceEntries || [];
|
||||
sharedObj.MonacoPerformanceMarks = sharedObj.MonacoPerformanceMarks || [];
|
||||
|
||||
const _dataLen = 2;
|
||||
const _timeStamp = typeof console.timeStamp === 'function' ? console.timeStamp.bind(console) : () => { };
|
||||
|
||||
function importEntries(entries) {
|
||||
sharedObj._performanceEntries.splice(0, 0, ...entries);
|
||||
sharedObj.MonacoPerformanceMarks.splice(0, 0, ...entries);
|
||||
}
|
||||
|
||||
function exportEntries() {
|
||||
return sharedObj._performanceEntries.slice(0);
|
||||
return sharedObj.MonacoPerformanceMarks.slice(0);
|
||||
}
|
||||
|
||||
function getEntries() {
|
||||
const result = [];
|
||||
const entries = sharedObj._performanceEntries;
|
||||
const entries = sharedObj.MonacoPerformanceMarks;
|
||||
for (let i = 0; i < entries.length; i += _dataLen) {
|
||||
result.push({
|
||||
name: entries[i],
|
||||
@@ -35,7 +35,7 @@ function _factory(sharedObj) {
|
||||
}
|
||||
|
||||
function getDuration(from, to) {
|
||||
const entries = sharedObj._performanceEntries;
|
||||
const entries = sharedObj.MonacoPerformanceMarks;
|
||||
let target = to;
|
||||
let endIndex = 0;
|
||||
for (let i = entries.length - _dataLen; i >= 0; i -= _dataLen) {
|
||||
@@ -54,7 +54,7 @@ function _factory(sharedObj) {
|
||||
}
|
||||
|
||||
function mark(name) {
|
||||
sharedObj._performanceEntries.push(name, Date.now());
|
||||
sharedObj.MonacoPerformanceMarks.push(name, Date.now());
|
||||
_timeStamp(name);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ function _factory(sharedObj) {
|
||||
// Because we want both instances to use the same perf-data
|
||||
// we store them globally
|
||||
|
||||
let sharedObj;
|
||||
// eslint-disable-next-line no-var
|
||||
var sharedObj;
|
||||
if (typeof global === 'object') {
|
||||
// nodejs
|
||||
sharedObj = global;
|
||||
@@ -91,5 +92,5 @@ if (typeof define === 'function') {
|
||||
// commonjs
|
||||
module.exports = _factory(sharedObj);
|
||||
} else {
|
||||
// invalid context...
|
||||
sharedObj.perf = _factory(sharedObj);
|
||||
}
|
||||
|
||||
@@ -474,7 +474,7 @@ export function peekReadable<T>(readable: Readable<T>, reducer: IReducer<T>, max
|
||||
/**
|
||||
* Helper to fully read a T stream into a T.
|
||||
*/
|
||||
export function consumeStream<T>(stream: ReadableStream<T>, reducer: IReducer<T>): Promise<T> {
|
||||
export function consumeStream<T>(stream: ReadableStreamEvents<T>, reducer: IReducer<T>): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const chunks: T[] = [];
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
/**
|
||||
* @returns whether the provided parameter is a JavaScript Array or not.
|
||||
*/
|
||||
export function isArray(array: any): array is any[] {
|
||||
export function isArray<T>(array: T | {}): array is T extends readonly any[] ? (unknown extends T ? never : readonly any[]) : any[] {
|
||||
return Array.isArray(array);
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ export function validateConstraint(arg: any, constraint: TypeConstraint | undefi
|
||||
if (arg instanceof constraint) {
|
||||
return;
|
||||
}
|
||||
} catch{
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
if (!isUndefinedOrNull(arg) && arg.constructor === constraint) {
|
||||
|
||||
@@ -252,7 +252,7 @@ export class URI implements UriComponents {
|
||||
return this;
|
||||
}
|
||||
|
||||
return new _URI(scheme, authority, path, query, fragment);
|
||||
return new CachingURI(scheme, authority, path, query, fragment);
|
||||
}
|
||||
|
||||
// ---- parse & validate ------------------------
|
||||
@@ -266,9 +266,9 @@ export class URI implements UriComponents {
|
||||
static parse(value: string, _strict: boolean = false): URI {
|
||||
const match = _regexp.exec(value);
|
||||
if (!match) {
|
||||
return new _URI(_empty, _empty, _empty, _empty, _empty);
|
||||
return new CachingURI(_empty, _empty, _empty, _empty, _empty);
|
||||
}
|
||||
return new _URI(
|
||||
return new CachingURI(
|
||||
match[2] || _empty,
|
||||
percentDecode(match[4] || _empty),
|
||||
percentDecode(match[5] || _empty),
|
||||
@@ -323,11 +323,11 @@ export class URI implements UriComponents {
|
||||
}
|
||||
}
|
||||
|
||||
return new _URI('file', authority, path, _empty, _empty);
|
||||
return new CachingURI('file', authority, path, _empty, _empty);
|
||||
}
|
||||
|
||||
static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
|
||||
return new _URI(
|
||||
return new CachingURI(
|
||||
components.scheme,
|
||||
components.authority,
|
||||
components.path,
|
||||
@@ -388,7 +388,7 @@ export class URI implements UriComponents {
|
||||
} else if (data instanceof URI) {
|
||||
return data;
|
||||
} else {
|
||||
const result = new _URI(data);
|
||||
const result = new CachingURI(data);
|
||||
result._formatted = (<UriState>data).external;
|
||||
result._fsPath = (<UriState>data)._sep === _pathSepMarker ? (<UriState>data).fsPath : null;
|
||||
return result;
|
||||
@@ -413,8 +413,8 @@ interface UriState extends UriComponents {
|
||||
|
||||
const _pathSepMarker = isWindows ? 1 : undefined;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
class _URI extends URI {
|
||||
// This class exists so that URI is compatibile with vscode.Uri (API).
|
||||
class CachingURI extends URI {
|
||||
|
||||
_formatted: string | null = null;
|
||||
_fsPath: string | null = null;
|
||||
|
||||
@@ -457,7 +457,7 @@ export namespace win32 {
|
||||
|
||||
async function fileExists(path: string): Promise<boolean> {
|
||||
if (await promisify(fs.exists)(path)) {
|
||||
return !((await promisify(fs.stat)(path)).isDirectory);
|
||||
return !((await promisify(fs.stat)(path)).isDirectory());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ export interface IPopupOptions {
|
||||
x?: number;
|
||||
y?: number;
|
||||
positioningItem?: number;
|
||||
onHide?: () => void;
|
||||
}
|
||||
|
||||
export const CONTEXT_MENU_CHANNEL = 'vscode:contextmenu';
|
||||
export const CONTEXT_MENU_CLOSE_CHANNEL = 'vscode:onCloseContextMenu';
|
||||
export const CONTEXT_MENU_CLOSE_CHANNEL = 'vscode:onCloseContextMenu';
|
||||
|
||||
@@ -9,9 +9,10 @@ import { ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_
|
||||
export function registerContextMenuListener(): void {
|
||||
ipcMain.on(CONTEXT_MENU_CHANNEL, (event: IpcMainEvent, contextMenuId: number, items: ISerializableContextMenuItem[], onClickChannel: string, options?: IPopupOptions) => {
|
||||
const menu = createMenu(event, onClickChannel, items);
|
||||
const window = BrowserWindow.fromWebContents(event.sender);
|
||||
|
||||
menu.popup({
|
||||
window: BrowserWindow.fromWebContents(event.sender),
|
||||
window: window ? window : undefined,
|
||||
x: options ? options.x : undefined,
|
||||
y: options ? options.y : undefined,
|
||||
positioningItem: options ? options.positioningItem : undefined,
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IContextMenuItem, ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHAN
|
||||
|
||||
let contextMenuIdPool = 0;
|
||||
|
||||
export function popup(items: IContextMenuItem[], options?: IPopupOptions): void {
|
||||
export function popup(items: IContextMenuItem[], options?: IPopupOptions, onHide?: () => void): void {
|
||||
const processedItems: IContextMenuItem[] = [];
|
||||
|
||||
const contextMenuId = contextMenuIdPool++;
|
||||
@@ -28,8 +28,8 @@ export function popup(items: IContextMenuItem[], options?: IPopupOptions): void
|
||||
|
||||
ipcRenderer.removeListener(onClickChannel, onClickChannelHandler);
|
||||
|
||||
if (options?.onHide) {
|
||||
options.onHide();
|
||||
if (onHide) {
|
||||
onHide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1230,10 +1230,10 @@ export class QuickInputController extends Disposable {
|
||||
this.previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined;
|
||||
}, true));
|
||||
this._register(focusTracker.onDidBlur(() => {
|
||||
this.previousFocusElement = undefined;
|
||||
if (!this.getUI().ignoreFocusOut && !this.options.ignoreFocusOut()) {
|
||||
this.hide(true);
|
||||
this.hide();
|
||||
}
|
||||
this.previousFocusElement = undefined;
|
||||
}));
|
||||
this._register(dom.addDisposableListener(container, dom.EventType.FOCUS, (e: FocusEvent) => {
|
||||
inputBox.setFocus();
|
||||
@@ -1574,13 +1574,14 @@ export class QuickInputController extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
hide(focusLost?: boolean) {
|
||||
hide() {
|
||||
const controller = this.controller;
|
||||
if (controller) {
|
||||
const focusChanged = !this.ui?.container.contains(document.activeElement);
|
||||
this.controller = null;
|
||||
this.onHideEmitter.fire();
|
||||
this.getUI().container.style.display = 'none';
|
||||
if (!focusLost) {
|
||||
if (!focusChanged) {
|
||||
if (this.previousFocusElement && this.previousFocusElement.offsetParent) {
|
||||
this.previousFocusElement.focus();
|
||||
this.previousFocusElement = undefined;
|
||||
|
||||
@@ -68,14 +68,6 @@
|
||||
*/
|
||||
webFrame: {
|
||||
|
||||
getZoomFactor() {
|
||||
return webFrame.getZoomFactor();
|
||||
},
|
||||
|
||||
getZoomLevel() {
|
||||
return webFrame.getZoomLevel();
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} level
|
||||
*/
|
||||
|
||||
@@ -43,16 +43,6 @@ export const ipcRenderer = (window as any).vscode.ipcRenderer as {
|
||||
|
||||
export const webFrame = (window as any).vscode.webFrame as {
|
||||
|
||||
/**
|
||||
* The current zoom factor.
|
||||
*/
|
||||
getZoomFactor(): number;
|
||||
|
||||
/**
|
||||
* The current zoom level.
|
||||
*/
|
||||
getZoomLevel(): number;
|
||||
|
||||
/**
|
||||
* Changes the zoom level to the specified level. The original size is 0 and each
|
||||
* increment above or below represents zooming 20% larger or smaller to default
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { guessMimeTypes, registerTextMime, suggestFilename } from 'vs/base/common/mime';
|
||||
import { guessMimeTypes, registerTextMime } from 'vs/base/common/mime';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
suite('Mime', () => {
|
||||
@@ -126,53 +126,4 @@ suite('Mime', () => {
|
||||
|
||||
assert.deepEqual(guessMimeTypes(URI.parse(`data:;label:something.data;description:data,`)), ['text/data', 'text/plain']);
|
||||
});
|
||||
|
||||
test('Filename Suggestion - Suggest prefix only when there are no relevant extensions', () => {
|
||||
const id = 'plumbus0';
|
||||
const mime = `text/${id}`;
|
||||
for (let extension of ['one', 'two']) {
|
||||
registerTextMime({ id, mime, extension });
|
||||
}
|
||||
|
||||
let suggested = suggestFilename('shleem', 'Untitled-1');
|
||||
assert.equal(suggested, 'Untitled-1');
|
||||
});
|
||||
|
||||
test('Filename Suggestion - Suggest prefix with first extension that begins with a dot', () => {
|
||||
const id = 'plumbus1';
|
||||
const mime = `text/${id}`;
|
||||
for (let extension of ['plumbus', '.shleem', '.gazorpazorp']) {
|
||||
registerTextMime({ id, mime, extension });
|
||||
}
|
||||
|
||||
let suggested = suggestFilename('plumbus1', 'Untitled-1');
|
||||
assert.equal(suggested, 'Untitled-1.shleem');
|
||||
});
|
||||
|
||||
test('Filename Suggestion - Suggest first relevant extension when there are none that begin with a dot', () => {
|
||||
const id = 'plumbus2';
|
||||
const mime = `text/${id}`;
|
||||
for (let extension of ['plumbus', 'shleem', 'gazorpazorp']) {
|
||||
registerTextMime({ id, mime, extension });
|
||||
}
|
||||
|
||||
let suggested = suggestFilename('plumbus2', 'Untitled-1');
|
||||
assert.equal(suggested, 'plumbus');
|
||||
});
|
||||
|
||||
test('Filename Suggestion - Should ignore user-configured associations', () => {
|
||||
registerTextMime({ id: 'plumbus3', mime: 'text/plumbus3', extension: 'plumbus', userConfigured: true });
|
||||
registerTextMime({ id: 'plumbus3', mime: 'text/plumbus3', extension: '.shleem', userConfigured: true });
|
||||
registerTextMime({ id: 'plumbus3', mime: 'text/plumbus3', extension: '.gazorpazorp', userConfigured: false });
|
||||
|
||||
let suggested = suggestFilename('plumbus3', 'Untitled-1');
|
||||
assert.equal(suggested, 'Untitled-1.gazorpazorp');
|
||||
|
||||
registerTextMime({ id: 'plumbus4', mime: 'text/plumbus4', extension: 'plumbus', userConfigured: true });
|
||||
registerTextMime({ id: 'plumbus4', mime: 'text/plumbus4', extension: '.shleem', userConfigured: true });
|
||||
registerTextMime({ id: 'plumbus4', mime: 'text/plumbus4', extension: '.gazorpazorp', userConfigured: true });
|
||||
|
||||
suggested = suggestFilename('plumbus4', 'Untitled-1');
|
||||
assert.equal(suggested, 'Untitled-1');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || [];
|
||||
globalThis.MonacoPerformanceMarks.push('renderer/started', Date.now());
|
||||
</script>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
@@ -29,6 +33,7 @@
|
||||
// NOTE: Changes to inline scripts require update of content security policy
|
||||
self.require = {
|
||||
baseUrl: `${window.location.origin}/static/out`,
|
||||
recordStats: true,
|
||||
paths: {
|
||||
'vscode-textmate': `${window.location.origin}/static/remote/web/node_modules/vscode-textmate/release/main`,
|
||||
'vscode-oniguruma': `${window.location.origin}/static/remote/web/node_modules/vscode-oniguruma/release/main`,
|
||||
@@ -90,7 +95,11 @@
|
||||
<script src="./static/remote/web/node_modules/slickgrid/plugins/slick.cellrangedecorator.js"></script>
|
||||
<script src="./static/remote/web/node_modules/zone.js/dist/zone.min.js"></script>
|
||||
<script src="./static/remote/web/node_modules/reflect-metadata/Reflect.js"></script>
|
||||
<script src="./static/out/vs/base/common/performance.js"></script>
|
||||
<script src="./static/out/vs/loader.js"></script>
|
||||
<script>
|
||||
globalThis.MonacoPerformanceMarks.push('willLoadWorkbenchMain', Date.now());
|
||||
</script>
|
||||
<script>
|
||||
// NOTE: Changes to inline scripts require update of content security policy
|
||||
require(['vs/code/browser/workbench/workbench'], function() {});
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || [];
|
||||
globalThis.MonacoPerformanceMarks.push('renderer/started', Date.now());
|
||||
</script>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
@@ -30,6 +34,7 @@
|
||||
// NOTE: Changes to inline scripts require update of content security policy
|
||||
self.require = {
|
||||
baseUrl: `${window.location.origin}/static/out`,
|
||||
recordStats: true,
|
||||
paths: {
|
||||
'vscode-textmate': `${window.location.origin}/static/node_modules/vscode-textmate/release/main`,
|
||||
'vscode-oniguruma': `${window.location.origin}/static/node_modules/vscode-oniguruma/release/main`,
|
||||
@@ -79,6 +84,9 @@
|
||||
<script src="./static/node_modules/zone.js/dist/zone.min.js"></script>
|
||||
<script src="./static/node_modules/reflect-metadata/Reflect.js"></script>
|
||||
<script src="./static/out/vs/loader.js"></script>
|
||||
<script>
|
||||
globalThis.MonacoPerformanceMarks.push('willLoadWorkbenchMain', Date.now());
|
||||
</script>
|
||||
<script src="./static/out/vs/workbench/workbench.web.api.nls.js"></script>
|
||||
<script src="./static/out/vs/workbench/workbench.web.api.js"></script>
|
||||
<script src="./static/out/vs/code/browser/workbench/workbench.js"></script>
|
||||
|
||||
@@ -12,6 +12,7 @@ import { request } from 'vs/base/parts/request/browser/request';
|
||||
import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/windows/common/windows';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { isStandalone } from 'vs/base/browser/browser';
|
||||
import { mark } from 'vs/base/common/performance';
|
||||
|
||||
interface ICredential {
|
||||
service: string;
|
||||
@@ -277,6 +278,10 @@ class WorkspaceProvider implements IWorkspaceProvider {
|
||||
|
||||
(function () {
|
||||
|
||||
// Mark start of workbench
|
||||
mark('didLoadWorkbenchMain');
|
||||
performance.mark('workbench-start');
|
||||
|
||||
// Find config by checking for DOM
|
||||
const configElement = document.getElementById('vscode-workbench-web-configuration');
|
||||
const configElementAttribute = configElement ? configElement.getAttribute('data-settings') : undefined;
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/issueReporter';
|
||||
import { ElectronService, IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
|
||||
import { ipcRenderer, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded
|
||||
import * as os from 'os';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import { ElectronService, IElectronService } from 'vs/platform/electron/electron-sandbox/electron';
|
||||
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window';
|
||||
import { $, windowOpenNoOpener, addClass } from 'vs/base/browser/dom';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded
|
||||
import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel';
|
||||
import * as collections from 'vs/base/common/collections';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
@@ -152,7 +152,7 @@ export class IssueReporter extends Disposable {
|
||||
|
||||
this.setUpTypes();
|
||||
this.setEventHandlers();
|
||||
this.applyZoom(configuration.data.zoomLevel);
|
||||
applyZoom(configuration.data.zoomLevel);
|
||||
this.applyStyles(configuration.data.styles);
|
||||
this.handleExtensionData(configuration.data.enabledExtensions);
|
||||
|
||||
@@ -180,15 +180,6 @@ export class IssueReporter extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private applyZoom(zoomLevel: number) {
|
||||
webFrame.setZoomLevel(zoomLevel);
|
||||
browser.setZoomFactor(webFrame.getZoomFactor());
|
||||
// See https://github.com/Microsoft/vscode/issues/26151
|
||||
// Cannot be trusted because the webFrame might take some time
|
||||
// until it really applies the new zoom level
|
||||
browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false);
|
||||
}
|
||||
|
||||
private applyStyles(styles: IssueReporterStyles) {
|
||||
const styleTag = document.createElement('style');
|
||||
const content: string[] = [];
|
||||
@@ -505,12 +496,12 @@ export class IssueReporter extends Disposable {
|
||||
|
||||
// Cmd/Ctrl + zooms in
|
||||
if (cmdOrCtrlKey && e.keyCode === 187) {
|
||||
this.applyZoom(webFrame.getZoomLevel() + 1);
|
||||
zoomIn();
|
||||
}
|
||||
|
||||
// Cmd/Ctrl - zooms out
|
||||
if (cmdOrCtrlKey && e.keyCode === 189) {
|
||||
this.applyZoom(webFrame.getZoomLevel() - 1);
|
||||
zoomOut();
|
||||
}
|
||||
|
||||
// With latest electron upgrade, cmd+a is no longer propagating correctly for inputs in this window on mac
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
|
||||
import 'vs/css!./media/processExplorer';
|
||||
import { clipboard } from 'electron';
|
||||
import { webFrame, ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import { repeat } from 'vs/base/common/strings';
|
||||
import { totalmem } from 'os';
|
||||
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/common/issue';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu';
|
||||
import { popup } from 'vs/base/parts/contextmenu/electron-sandbox/contextmenu';
|
||||
@@ -20,13 +19,8 @@ import { addDisposableListener, addClass } from 'vs/base/browser/dom';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { isRemoteDiagnosticError, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
|
||||
|
||||
let mapPidToWindowTitle = new Map<number, string>();
|
||||
|
||||
const DEBUG_FLAGS_PATTERN = /\s--(inspect|debug)(-brk|port)?=(\d+)?/;
|
||||
const DEBUG_PORT_PATTERN = /\s--(inspect|debug)-port=(\d+)/;
|
||||
const listeners = new DisposableStore();
|
||||
const collapsedStateCache: Map<string, boolean> = new Map<string, boolean>();
|
||||
let lastRequestTime: number;
|
||||
|
||||
interface FormattedProcessItem {
|
||||
cpu: number;
|
||||
@@ -37,391 +31,400 @@ interface FormattedProcessItem {
|
||||
cmd: string;
|
||||
}
|
||||
|
||||
function getProcessList(rootProcess: ProcessItem, isLocal: boolean): FormattedProcessItem[] {
|
||||
const processes: FormattedProcessItem[] = [];
|
||||
class ProcessExplorer {
|
||||
private lastRequestTime: number;
|
||||
|
||||
if (rootProcess) {
|
||||
getProcessItem(processes, rootProcess, 0, isLocal);
|
||||
private collapsedStateCache: Map<string, boolean> = new Map<string, boolean>();
|
||||
|
||||
private mapPidToWindowTitle = new Map<number, string>();
|
||||
|
||||
private listeners = new DisposableStore();
|
||||
|
||||
constructor(data: ProcessExplorerData) {
|
||||
this.applyStyles(data.styles);
|
||||
|
||||
// Map window process pids to titles, annotate process names with this when rendering to distinguish between them
|
||||
ipcRenderer.on('vscode:windowsInfoResponse', (event: unknown, windows: any[]) => {
|
||||
this.mapPidToWindowTitle = new Map<number, string>();
|
||||
windows.forEach(window => this.mapPidToWindowTitle.set(window.pid, window.title));
|
||||
});
|
||||
|
||||
ipcRenderer.on('vscode:listProcessesResponse', (event: unknown, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => {
|
||||
this.updateProcessInfo(processRoots);
|
||||
this.requestProcessList(0);
|
||||
});
|
||||
|
||||
this.lastRequestTime = Date.now();
|
||||
ipcRenderer.send('vscode:windowsInfoRequest');
|
||||
ipcRenderer.send('vscode:listProcesses');
|
||||
}
|
||||
|
||||
return processes;
|
||||
}
|
||||
private getProcessList(rootProcess: ProcessItem, isLocal: boolean): FormattedProcessItem[] {
|
||||
const processes: FormattedProcessItem[] = [];
|
||||
|
||||
function getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, indent: number, isLocal: boolean): void {
|
||||
const isRoot = (indent === 0);
|
||||
if (rootProcess) {
|
||||
this.getProcessItem(processes, rootProcess, 0, isLocal);
|
||||
}
|
||||
|
||||
const MB = 1024 * 1024;
|
||||
|
||||
let name = item.name;
|
||||
if (isRoot) {
|
||||
name = isLocal ? `${product.applicationName} main` : 'remote agent';
|
||||
return processes;
|
||||
}
|
||||
|
||||
if (name === 'window') {
|
||||
const windowTitle = mapPidToWindowTitle.get(item.pid);
|
||||
name = windowTitle !== undefined ? `${name} (${mapPidToWindowTitle.get(item.pid)})` : name;
|
||||
private getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, indent: number, isLocal: boolean): void {
|
||||
const isRoot = (indent === 0);
|
||||
|
||||
const MB = 1024 * 1024;
|
||||
|
||||
let name = item.name;
|
||||
if (isRoot) {
|
||||
name = isLocal ? `${product.applicationName} main` : 'remote agent';
|
||||
}
|
||||
|
||||
if (name === 'window') {
|
||||
const windowTitle = this.mapPidToWindowTitle.get(item.pid);
|
||||
name = windowTitle !== undefined ? `${name} (${this.mapPidToWindowTitle.get(item.pid)})` : name;
|
||||
}
|
||||
|
||||
// Format name with indent
|
||||
const formattedName = isRoot ? name : `${' '.repeat(indent)} ${name}`;
|
||||
const memory = process.platform === 'win32' ? item.mem : (totalmem() * (item.mem / 100));
|
||||
processes.push({
|
||||
cpu: item.load,
|
||||
memory: (memory / MB),
|
||||
pid: item.pid.toFixed(0),
|
||||
name,
|
||||
formattedName,
|
||||
cmd: item.cmd
|
||||
});
|
||||
|
||||
// Recurse into children if any
|
||||
if (Array.isArray(item.children)) {
|
||||
item.children.forEach(child => {
|
||||
if (child) {
|
||||
this.getProcessItem(processes, child, indent + 1, isLocal);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Format name with indent
|
||||
const formattedName = isRoot ? name : `${repeat(' ', indent)} ${name}`;
|
||||
const memory = process.platform === 'win32' ? item.mem : (totalmem() * (item.mem / 100));
|
||||
processes.push({
|
||||
cpu: item.load,
|
||||
memory: (memory / MB),
|
||||
pid: item.pid.toFixed(0),
|
||||
name,
|
||||
formattedName,
|
||||
cmd: item.cmd
|
||||
});
|
||||
private isDebuggable(cmd: string): boolean {
|
||||
const matches = DEBUG_FLAGS_PATTERN.exec(cmd);
|
||||
return (matches && matches.length >= 2) || cmd.indexOf('node ') >= 0 || cmd.indexOf('node.exe') >= 0;
|
||||
}
|
||||
|
||||
// Recurse into children if any
|
||||
if (Array.isArray(item.children)) {
|
||||
item.children.forEach(child => {
|
||||
if (child) {
|
||||
getProcessItem(processes, child, indent + 1, isLocal);
|
||||
private attachTo(item: FormattedProcessItem) {
|
||||
const config: any = {
|
||||
type: 'node',
|
||||
request: 'attach',
|
||||
name: `process ${item.pid}`
|
||||
};
|
||||
|
||||
let matches = DEBUG_FLAGS_PATTERN.exec(item.cmd);
|
||||
if (matches && matches.length >= 2) {
|
||||
// attach via port
|
||||
if (matches.length === 4 && matches[3]) {
|
||||
config.port = parseInt(matches[3]);
|
||||
}
|
||||
config.protocol = matches[1] === 'debug' ? 'legacy' : 'inspector';
|
||||
} else {
|
||||
// no port -> try to attach via pid (send SIGUSR1)
|
||||
config.processId = String(item.pid);
|
||||
}
|
||||
|
||||
// a debug-port=n or inspect-port=n overrides the port
|
||||
matches = DEBUG_PORT_PATTERN.exec(item.cmd);
|
||||
if (matches && matches.length === 3) {
|
||||
// override port
|
||||
config.port = parseInt(matches[2]);
|
||||
}
|
||||
|
||||
ipcRenderer.send('vscode:workbenchCommand', { id: 'debug.startFromConfig', from: 'processExplorer', args: [config] });
|
||||
}
|
||||
|
||||
private getProcessIdWithHighestProperty(processList: any[], propertyName: string) {
|
||||
let max = 0;
|
||||
let maxProcessId;
|
||||
processList.forEach(process => {
|
||||
if (process[propertyName] > max) {
|
||||
max = process[propertyName];
|
||||
maxProcessId = process.pid;
|
||||
}
|
||||
});
|
||||
|
||||
return maxProcessId;
|
||||
}
|
||||
}
|
||||
|
||||
function isDebuggable(cmd: string): boolean {
|
||||
const matches = DEBUG_FLAGS_PATTERN.exec(cmd);
|
||||
return (matches && matches.length >= 2) || cmd.indexOf('node ') >= 0 || cmd.indexOf('node.exe') >= 0;
|
||||
}
|
||||
|
||||
function attachTo(item: FormattedProcessItem) {
|
||||
const config: any = {
|
||||
type: 'node',
|
||||
request: 'attach',
|
||||
name: `process ${item.pid}`
|
||||
};
|
||||
|
||||
let matches = DEBUG_FLAGS_PATTERN.exec(item.cmd);
|
||||
if (matches && matches.length >= 2) {
|
||||
// attach via port
|
||||
if (matches.length === 4 && matches[3]) {
|
||||
config.port = parseInt(matches[3]);
|
||||
private updateSectionCollapsedState(shouldExpand: boolean, body: HTMLElement, twistie: HTMLImageElement, sectionName: string) {
|
||||
if (shouldExpand) {
|
||||
body.classList.remove('hidden');
|
||||
this.collapsedStateCache.set(sectionName, false);
|
||||
twistie.src = './media/expanded.svg';
|
||||
} else {
|
||||
body.classList.add('hidden');
|
||||
this.collapsedStateCache.set(sectionName, true);
|
||||
twistie.src = './media/collapsed.svg';
|
||||
}
|
||||
config.protocol = matches[1] === 'debug' ? 'legacy' : 'inspector';
|
||||
} else {
|
||||
// no port -> try to attach via pid (send SIGUSR1)
|
||||
config.processId = String(item.pid);
|
||||
}
|
||||
|
||||
// a debug-port=n or inspect-port=n overrides the port
|
||||
matches = DEBUG_PORT_PATTERN.exec(item.cmd);
|
||||
if (matches && matches.length === 3) {
|
||||
// override port
|
||||
config.port = parseInt(matches[2]);
|
||||
}
|
||||
|
||||
ipcRenderer.send('vscode:workbenchCommand', { id: 'debug.startFromConfig', from: 'processExplorer', args: [config] });
|
||||
}
|
||||
|
||||
function getProcessIdWithHighestProperty(processList: any[], propertyName: string) {
|
||||
let max = 0;
|
||||
let maxProcessId;
|
||||
processList.forEach(process => {
|
||||
if (process[propertyName] > max) {
|
||||
max = process[propertyName];
|
||||
maxProcessId = process.pid;
|
||||
private renderProcessFetchError(sectionName: string, errorMessage: string) {
|
||||
const container = document.getElementById('process-list');
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return maxProcessId;
|
||||
}
|
||||
const body = document.createElement('tbody');
|
||||
|
||||
function updateSectionCollapsedState(shouldExpand: boolean, body: HTMLElement, twistie: HTMLImageElement, sectionName: string) {
|
||||
if (shouldExpand) {
|
||||
body.classList.remove('hidden');
|
||||
collapsedStateCache.set(sectionName, false);
|
||||
twistie.src = './media/expanded.svg';
|
||||
} else {
|
||||
body.classList.add('hidden');
|
||||
collapsedStateCache.set(sectionName, true);
|
||||
twistie.src = './media/collapsed.svg';
|
||||
}
|
||||
}
|
||||
this.renderProcessGroupHeader(sectionName, body, container);
|
||||
|
||||
function renderProcessFetchError(sectionName: string, errorMessage: string) {
|
||||
const container = document.getElementById('process-list');
|
||||
if (!container) {
|
||||
return;
|
||||
const errorRow = document.createElement('tr');
|
||||
const data = document.createElement('td');
|
||||
data.textContent = errorMessage;
|
||||
data.className = 'error';
|
||||
data.colSpan = 4;
|
||||
errorRow.appendChild(data);
|
||||
|
||||
body.appendChild(errorRow);
|
||||
container.appendChild(body);
|
||||
}
|
||||
|
||||
const body = document.createElement('tbody');
|
||||
private renderProcessGroupHeader(sectionName: string, body: HTMLElement, container: HTMLElement) {
|
||||
const headerRow = document.createElement('tr');
|
||||
const data = document.createElement('td');
|
||||
data.textContent = sectionName;
|
||||
data.colSpan = 4;
|
||||
headerRow.appendChild(data);
|
||||
|
||||
renderProcessGroupHeader(sectionName, body, container);
|
||||
const twistie = document.createElement('img');
|
||||
this.updateSectionCollapsedState(!this.collapsedStateCache.get(sectionName), body, twistie, sectionName);
|
||||
data.prepend(twistie);
|
||||
|
||||
const errorRow = document.createElement('tr');
|
||||
const data = document.createElement('td');
|
||||
data.textContent = errorMessage;
|
||||
data.className = 'error';
|
||||
data.colSpan = 4;
|
||||
errorRow.appendChild(data);
|
||||
|
||||
body.appendChild(errorRow);
|
||||
container.appendChild(body);
|
||||
}
|
||||
|
||||
function renderProcessGroupHeader(sectionName: string, body: HTMLElement, container: HTMLElement) {
|
||||
const headerRow = document.createElement('tr');
|
||||
const data = document.createElement('td');
|
||||
data.textContent = sectionName;
|
||||
data.colSpan = 4;
|
||||
headerRow.appendChild(data);
|
||||
|
||||
const twistie = document.createElement('img');
|
||||
updateSectionCollapsedState(!collapsedStateCache.get(sectionName), body, twistie, sectionName);
|
||||
data.prepend(twistie);
|
||||
|
||||
listeners.add(addDisposableListener(data, 'click', (e) => {
|
||||
const isHidden = body.classList.contains('hidden');
|
||||
updateSectionCollapsedState(isHidden, body, twistie, sectionName);
|
||||
}));
|
||||
|
||||
container.appendChild(headerRow);
|
||||
}
|
||||
|
||||
function renderTableSection(sectionName: string, processList: FormattedProcessItem[], renderManySections: boolean, sectionIsLocal: boolean): void {
|
||||
const container = document.getElementById('process-list');
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
const highestCPUProcess = getProcessIdWithHighestProperty(processList, 'cpu');
|
||||
const highestMemoryProcess = getProcessIdWithHighestProperty(processList, 'memory');
|
||||
|
||||
const body = document.createElement('tbody');
|
||||
|
||||
if (renderManySections) {
|
||||
renderProcessGroupHeader(sectionName, body, container);
|
||||
}
|
||||
|
||||
processList.forEach(p => {
|
||||
const row = document.createElement('tr');
|
||||
row.id = p.pid.toString();
|
||||
|
||||
const cpu = document.createElement('td');
|
||||
p.pid === highestCPUProcess
|
||||
? cpu.classList.add('centered', 'highest')
|
||||
: cpu.classList.add('centered');
|
||||
cpu.textContent = p.cpu.toFixed(0);
|
||||
|
||||
const memory = document.createElement('td');
|
||||
p.pid === highestMemoryProcess
|
||||
? memory.classList.add('centered', 'highest')
|
||||
: memory.classList.add('centered');
|
||||
memory.textContent = p.memory.toFixed(0);
|
||||
|
||||
const pid = document.createElement('td');
|
||||
pid.classList.add('centered');
|
||||
pid.textContent = p.pid;
|
||||
|
||||
const name = document.createElement('th');
|
||||
name.scope = 'row';
|
||||
name.classList.add('data');
|
||||
name.title = p.cmd;
|
||||
name.textContent = p.formattedName;
|
||||
|
||||
row.append(cpu, memory, pid, name);
|
||||
|
||||
listeners.add(addDisposableListener(row, 'contextmenu', (e) => {
|
||||
showContextMenu(e, p, sectionIsLocal);
|
||||
this.listeners.add(addDisposableListener(data, 'click', (e) => {
|
||||
const isHidden = body.classList.contains('hidden');
|
||||
this.updateSectionCollapsedState(isHidden, body, twistie, sectionName);
|
||||
}));
|
||||
|
||||
body.appendChild(row);
|
||||
});
|
||||
|
||||
container.appendChild(body);
|
||||
}
|
||||
|
||||
function updateProcessInfo(processLists: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]): void {
|
||||
const container = document.getElementById('process-list');
|
||||
if (!container) {
|
||||
return;
|
||||
container.appendChild(headerRow);
|
||||
}
|
||||
|
||||
container.innerHTML = '';
|
||||
listeners.clear();
|
||||
|
||||
const tableHead = document.createElement('thead');
|
||||
tableHead.innerHTML = `<tr>
|
||||
<th scope="col" class="cpu">${localize('cpu', "CPU %")}</th>
|
||||
<th scope="col" class="memory">${localize('memory', "Memory (MB)")}</th>
|
||||
<th scope="col" class="pid">${localize('pid', "pid")}</th>
|
||||
<th scope="col" class="nameLabel">${localize('name', "Name")}</th>
|
||||
</tr>`;
|
||||
|
||||
container.append(tableHead);
|
||||
|
||||
const hasMultipleMachines = Object.keys(processLists).length > 1;
|
||||
processLists.forEach((remote, i) => {
|
||||
const isLocal = i === 0;
|
||||
if (isRemoteDiagnosticError(remote.rootProcess)) {
|
||||
renderProcessFetchError(remote.name, remote.rootProcess.errorMessage);
|
||||
} else {
|
||||
renderTableSection(remote.name, getProcessList(remote.rootProcess, isLocal), hasMultipleMachines, isLocal);
|
||||
private renderTableSection(sectionName: string, processList: FormattedProcessItem[], renderManySections: boolean, sectionIsLocal: boolean): void {
|
||||
const container = document.getElementById('process-list');
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function applyStyles(styles: ProcessExplorerStyles): void {
|
||||
const styleTag = document.createElement('style');
|
||||
const content: string[] = [];
|
||||
const highestCPUProcess = this.getProcessIdWithHighestProperty(processList, 'cpu');
|
||||
const highestMemoryProcess = this.getProcessIdWithHighestProperty(processList, 'memory');
|
||||
|
||||
if (styles.hoverBackground) {
|
||||
content.push(`tbody > tr:hover, table > tr:hover { background-color: ${styles.hoverBackground}; }`);
|
||||
const body = document.createElement('tbody');
|
||||
|
||||
if (renderManySections) {
|
||||
this.renderProcessGroupHeader(sectionName, body, container);
|
||||
}
|
||||
|
||||
processList.forEach(p => {
|
||||
const row = document.createElement('tr');
|
||||
row.id = p.pid.toString();
|
||||
|
||||
const cpu = document.createElement('td');
|
||||
p.pid === highestCPUProcess
|
||||
? cpu.classList.add('centered', 'highest')
|
||||
: cpu.classList.add('centered');
|
||||
cpu.textContent = p.cpu.toFixed(0);
|
||||
|
||||
const memory = document.createElement('td');
|
||||
p.pid === highestMemoryProcess
|
||||
? memory.classList.add('centered', 'highest')
|
||||
: memory.classList.add('centered');
|
||||
memory.textContent = p.memory.toFixed(0);
|
||||
|
||||
const pid = document.createElement('td');
|
||||
pid.classList.add('centered');
|
||||
pid.textContent = p.pid;
|
||||
|
||||
const name = document.createElement('th');
|
||||
name.scope = 'row';
|
||||
name.classList.add('data');
|
||||
name.title = p.cmd;
|
||||
name.textContent = p.formattedName;
|
||||
|
||||
row.append(cpu, memory, pid, name);
|
||||
|
||||
this.listeners.add(addDisposableListener(row, 'contextmenu', (e) => {
|
||||
this.showContextMenu(e, p, sectionIsLocal);
|
||||
}));
|
||||
|
||||
body.appendChild(row);
|
||||
});
|
||||
|
||||
container.appendChild(body);
|
||||
}
|
||||
|
||||
if (styles.hoverForeground) {
|
||||
content.push(`tbody > tr:hover, table > tr:hover { color: ${styles.hoverForeground}; }`);
|
||||
private updateProcessInfo(processLists: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]): void {
|
||||
const container = document.getElementById('process-list');
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = '';
|
||||
this.listeners.clear();
|
||||
|
||||
const tableHead = document.createElement('thead');
|
||||
tableHead.innerHTML = `<tr>
|
||||
<th scope="col" class="cpu">${localize('cpu', "CPU %")}</th>
|
||||
<th scope="col" class="memory">${localize('memory', "Memory (MB)")}</th>
|
||||
<th scope="col" class="pid">${localize('pid', "pid")}</th>
|
||||
<th scope="col" class="nameLabel">${localize('name', "Name")}</th>
|
||||
</tr>`;
|
||||
|
||||
container.append(tableHead);
|
||||
|
||||
const hasMultipleMachines = Object.keys(processLists).length > 1;
|
||||
processLists.forEach((remote, i) => {
|
||||
const isLocal = i === 0;
|
||||
if (isRemoteDiagnosticError(remote.rootProcess)) {
|
||||
this.renderProcessFetchError(remote.name, remote.rootProcess.errorMessage);
|
||||
} else {
|
||||
this.renderTableSection(remote.name, this.getProcessList(remote.rootProcess, isLocal), hasMultipleMachines, isLocal);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (styles.highlightForeground) {
|
||||
content.push(`.highest { color: ${styles.highlightForeground}; }`);
|
||||
private applyStyles(styles: ProcessExplorerStyles): void {
|
||||
const styleTag = document.createElement('style');
|
||||
const content: string[] = [];
|
||||
|
||||
if (styles.hoverBackground) {
|
||||
content.push(`tbody > tr:hover, table > tr:hover { background-color: ${styles.hoverBackground}; }`);
|
||||
}
|
||||
|
||||
if (styles.hoverForeground) {
|
||||
content.push(`tbody > tr:hover, table > tr:hover { color: ${styles.hoverForeground}; }`);
|
||||
}
|
||||
|
||||
if (styles.highlightForeground) {
|
||||
content.push(`.highest { color: ${styles.highlightForeground}; }`);
|
||||
}
|
||||
|
||||
styleTag.innerHTML = content.join('\n');
|
||||
if (document.head) {
|
||||
document.head.appendChild(styleTag);
|
||||
}
|
||||
if (styles.color) {
|
||||
document.body.style.color = styles.color;
|
||||
}
|
||||
}
|
||||
|
||||
styleTag.innerHTML = content.join('\n');
|
||||
if (document.head) {
|
||||
document.head.appendChild(styleTag);
|
||||
}
|
||||
if (styles.color) {
|
||||
document.body.style.color = styles.color;
|
||||
}
|
||||
}
|
||||
private showContextMenu(e: MouseEvent, item: FormattedProcessItem, isLocal: boolean) {
|
||||
e.preventDefault();
|
||||
|
||||
function applyZoom(zoomLevel: number): void {
|
||||
webFrame.setZoomLevel(zoomLevel);
|
||||
browser.setZoomFactor(webFrame.getZoomFactor());
|
||||
// See https://github.com/Microsoft/vscode/issues/26151
|
||||
// Cannot be trusted because the webFrame might take some time
|
||||
// until it really applies the new zoom level
|
||||
browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false);
|
||||
}
|
||||
const items: IContextMenuItem[] = [];
|
||||
const pid = Number(item.pid);
|
||||
|
||||
function showContextMenu(e: MouseEvent, item: FormattedProcessItem, isLocal: boolean) {
|
||||
e.preventDefault();
|
||||
if (isLocal) {
|
||||
items.push({
|
||||
label: localize('killProcess', "Kill Process"),
|
||||
click() {
|
||||
process.kill(pid, 'SIGTERM');
|
||||
}
|
||||
});
|
||||
|
||||
const items: IContextMenuItem[] = [];
|
||||
const pid = Number(item.pid);
|
||||
items.push({
|
||||
label: localize('forceKillProcess', "Force Kill Process"),
|
||||
click() {
|
||||
process.kill(pid, 'SIGKILL');
|
||||
}
|
||||
});
|
||||
|
||||
items.push({
|
||||
type: 'separator'
|
||||
});
|
||||
}
|
||||
|
||||
if (isLocal) {
|
||||
items.push({
|
||||
label: localize('killProcess', "Kill Process"),
|
||||
label: localize('copy', "Copy"),
|
||||
click() {
|
||||
process.kill(pid, 'SIGTERM');
|
||||
const row = document.getElementById(pid.toString());
|
||||
if (row) {
|
||||
clipboard.writeText(row.innerText);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
items.push({
|
||||
label: localize('forceKillProcess', "Force Kill Process"),
|
||||
label: localize('copyAll', "Copy All"),
|
||||
click() {
|
||||
process.kill(pid, 'SIGKILL');
|
||||
const processList = document.getElementById('process-list');
|
||||
if (processList) {
|
||||
clipboard.writeText(processList.innerText);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
items.push({
|
||||
type: 'separator'
|
||||
});
|
||||
if (item && isLocal && this.isDebuggable(item.cmd)) {
|
||||
items.push({
|
||||
type: 'separator'
|
||||
});
|
||||
|
||||
items.push({
|
||||
label: localize('debug', "Debug"),
|
||||
click: () => {
|
||||
this.attachTo(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
popup(items);
|
||||
}
|
||||
|
||||
items.push({
|
||||
label: localize('copy', "Copy"),
|
||||
click() {
|
||||
const row = document.getElementById(pid.toString());
|
||||
if (row) {
|
||||
clipboard.writeText(row.innerText);
|
||||
}
|
||||
}
|
||||
});
|
||||
private requestProcessList(totalWaitTime: number): void {
|
||||
setTimeout(() => {
|
||||
const nextRequestTime = Date.now();
|
||||
const waited = totalWaitTime + nextRequestTime - this.lastRequestTime;
|
||||
this.lastRequestTime = nextRequestTime;
|
||||
|
||||
items.push({
|
||||
label: localize('copyAll', "Copy All"),
|
||||
click() {
|
||||
const processList = document.getElementById('process-list');
|
||||
if (processList) {
|
||||
clipboard.writeText(processList.innerText);
|
||||
// Wait at least a second between requests.
|
||||
if (waited > 1000) {
|
||||
ipcRenderer.send('vscode:windowsInfoRequest');
|
||||
ipcRenderer.send('vscode:listProcesses');
|
||||
} else {
|
||||
this.requestProcessList(waited);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (item && isLocal && isDebuggable(item.cmd)) {
|
||||
items.push({
|
||||
type: 'separator'
|
||||
});
|
||||
|
||||
items.push({
|
||||
label: localize('debug', "Debug"),
|
||||
click() {
|
||||
attachTo(item);
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
|
||||
popup(items);
|
||||
public dispose() {
|
||||
this.listeners.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
function requestProcessList(totalWaitTime: number): void {
|
||||
setTimeout(() => {
|
||||
const nextRequestTime = Date.now();
|
||||
const waited = totalWaitTime + nextRequestTime - lastRequestTime;
|
||||
lastRequestTime = nextRequestTime;
|
||||
|
||||
// Wait at least a second between requests.
|
||||
if (waited > 1000) {
|
||||
ipcRenderer.send('vscode:windowsInfoRequest');
|
||||
ipcRenderer.send('vscode:listProcesses');
|
||||
} else {
|
||||
requestProcessList(waited);
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
|
||||
function createCloseListener(): void {
|
||||
// Cmd/Ctrl + w closes process explorer
|
||||
window.addEventListener('keydown', e => {
|
||||
const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey;
|
||||
if (cmdOrCtrlKey && e.keyCode === 87) {
|
||||
ipcRenderer.send('vscode:closeProcessExplorer');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function startup(data: ProcessExplorerData): void {
|
||||
const platformClass = platform.isWindows ? 'windows' : platform.isLinux ? 'linux' : 'mac';
|
||||
addClass(document.body, platformClass); // used by our fonts
|
||||
|
||||
applyStyles(data.styles);
|
||||
applyZoom(data.zoomLevel);
|
||||
createCloseListener();
|
||||
|
||||
// Map window process pids to titles, annotate process names with this when rendering to distinguish between them
|
||||
ipcRenderer.on('vscode:windowsInfoResponse', (event: unknown, windows: any[]) => {
|
||||
mapPidToWindowTitle = new Map<number, string>();
|
||||
windows.forEach(window => mapPidToWindowTitle.set(window.pid, window.title));
|
||||
});
|
||||
|
||||
ipcRenderer.on('vscode:listProcessesResponse', (event: unknown, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => {
|
||||
updateProcessInfo(processRoots);
|
||||
requestProcessList(0);
|
||||
});
|
||||
|
||||
lastRequestTime = Date.now();
|
||||
ipcRenderer.send('vscode:windowsInfoRequest');
|
||||
ipcRenderer.send('vscode:listProcesses');
|
||||
const processExplorer = new ProcessExplorer(data);
|
||||
|
||||
document.onkeydown = (e: KeyboardEvent) => {
|
||||
const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey;
|
||||
|
||||
// Cmd/Ctrl + zooms in
|
||||
if (cmdOrCtrlKey && e.keyCode === 187) {
|
||||
applyZoom(webFrame.getZoomLevel() + 1);
|
||||
zoomIn();
|
||||
}
|
||||
|
||||
// Cmd/Ctrl - zooms out
|
||||
if (cmdOrCtrlKey && e.keyCode === 189) {
|
||||
applyZoom(webFrame.getZoomLevel() - 1);
|
||||
zoomOut();
|
||||
}
|
||||
};
|
||||
|
||||
// Cmd/Ctrl + w closes process explorer
|
||||
window.addEventListener('keydown', e => {
|
||||
const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey;
|
||||
if (cmdOrCtrlKey && e.keyCode === 87) {
|
||||
processExplorer.dispose();
|
||||
ipcRenderer.send('vscode:closeProcessExplorer');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export class StorageDataCleaner extends Disposable {
|
||||
const emptyWorkspaces = workspaces.emptyWorkspaceInfos.map(info => info.backupFolder);
|
||||
|
||||
// Read all workspace storage folders that exist
|
||||
return readdir(this.environmentService.workspaceStorageHome).then(storageFolders => {
|
||||
return readdir(this.environmentService.workspaceStorageHome.fsPath).then(storageFolders => {
|
||||
const deletes: Promise<void>[] = [];
|
||||
|
||||
storageFolders.forEach(storageFolder => {
|
||||
@@ -44,7 +44,7 @@ export class StorageDataCleaner extends Disposable {
|
||||
}
|
||||
|
||||
if (emptyWorkspaces.indexOf(storageFolder) === -1) {
|
||||
deletes.push(rimraf(join(this.environmentService.workspaceStorageHome, storageFolder)));
|
||||
deletes.push(rimraf(join(this.environmentService.workspaceStorageHome.fsPath, storageFolder)));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
|
||||
server.registerChannel('userDataSyncAccount', authTokenChannel);
|
||||
|
||||
const userDataSyncService = accessor.get(IUserDataSyncService);
|
||||
const userDataSyncChannel = new UserDataSyncChannel(userDataSyncService, logService);
|
||||
const userDataSyncChannel = new UserDataSyncChannel(server, userDataSyncService, logService);
|
||||
server.registerChannel('userDataSync', userDataSyncChannel);
|
||||
|
||||
const userDataAutoSync = instantiationService2.createInstance(UserDataAutoSyncService);
|
||||
|
||||
@@ -9,41 +9,33 @@
|
||||
'use strict';
|
||||
|
||||
const perf = (function () {
|
||||
let sharedObj;
|
||||
if (typeof global === 'object') {
|
||||
// nodejs
|
||||
sharedObj = global;
|
||||
} else if (typeof self === 'object') {
|
||||
// browser
|
||||
sharedObj = self;
|
||||
} else {
|
||||
sharedObj = {};
|
||||
}
|
||||
// @ts-ignore
|
||||
sharedObj._performanceEntries = sharedObj._performanceEntries || [];
|
||||
globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || [];
|
||||
return {
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
mark(name) {
|
||||
sharedObj._performanceEntries.push(name, Date.now());
|
||||
globalThis.MonacoPerformanceMarks.push(name, Date.now());
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
perf.mark('renderer/started');
|
||||
|
||||
// Setup shell environment
|
||||
process['lazyEnv'] = getLazyEnv();
|
||||
|
||||
/**
|
||||
* @type {{ load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown }}
|
||||
* @type {{
|
||||
* load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown,
|
||||
* globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals')
|
||||
* }}
|
||||
*/
|
||||
const bootstrapWindow = (() => {
|
||||
// @ts-ignore (defined in bootstrap-window.js)
|
||||
return window.MonacoBootstrapWindow;
|
||||
})();
|
||||
|
||||
// Setup shell environment
|
||||
process['lazyEnv'] = getLazyEnv();
|
||||
|
||||
// Load workbench main JS, CSS and NLS all in parallel. This is an
|
||||
// optimization to prevent a waterfall of loading to happen, because
|
||||
// we know for a fact that workbench.desktop.main will depend on
|
||||
@@ -55,6 +47,8 @@ bootstrapWindow.load([
|
||||
'vs/css!vs/workbench/workbench.desktop.main'
|
||||
],
|
||||
function (workbench, configuration) {
|
||||
|
||||
// Mark start of workbench
|
||||
perf.mark('didLoadWorkbenchMain');
|
||||
performance.mark('workbench-start');
|
||||
|
||||
@@ -183,8 +177,7 @@ function showPartsSplash(configuration) {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function getLazyEnv() {
|
||||
|
||||
const ipc = require.__$__nodeRequire('electron').ipcRenderer;
|
||||
const ipcRenderer = bootstrapWindow.globals().ipcRenderer;
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
const handle = setTimeout(function () {
|
||||
@@ -192,13 +185,13 @@ function getLazyEnv() {
|
||||
console.warn('renderer did not receive lazyEnv in time');
|
||||
}, 10000);
|
||||
|
||||
ipc.once('vscode:acceptShellEnv', function (event, shellEnv) {
|
||||
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) {
|
||||
clearTimeout(handle);
|
||||
Object.assign(process.env, shellEnv);
|
||||
// @ts-ignore
|
||||
resolve(process.env);
|
||||
});
|
||||
|
||||
ipc.send('vscode:fetchShellEnv');
|
||||
ipcRenderer.send('vscode:fetchShellEnv');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { localize } from 'vs/nls';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { BrowserWindow, BrowserWindowConstructorOptions, app, AuthInfo, WebContents, Event as ElectronEvent } from 'electron';
|
||||
|
||||
type LoginEvent = {
|
||||
@@ -58,10 +59,12 @@ export class ProxyAuthHandler extends Disposable {
|
||||
show: true,
|
||||
title: 'VS Code',
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
preload: URI.parse(require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js')).fsPath,
|
||||
enableWebSQL: false,
|
||||
sandbox: true,
|
||||
devTools: false,
|
||||
enableRemoteModule: false,
|
||||
nativeWindowOpen: true
|
||||
v8CacheOptions: 'bypassHeatCheck'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -72,24 +75,27 @@ export class ProxyAuthHandler extends Disposable {
|
||||
}
|
||||
|
||||
const win = new BrowserWindow(opts);
|
||||
const config = {};
|
||||
const baseUrl = require.toUrl('vs/code/electron-browser/proxy/auth.html');
|
||||
const url = `${baseUrl}?config=${encodeURIComponent(JSON.stringify(config))}`;
|
||||
const url = require.toUrl('vs/code/electron-sandbox/proxy/auth.html');
|
||||
const proxyUrl = `${authInfo.host}:${authInfo.port}`;
|
||||
const title = localize('authRequire', "Proxy Authentication Required");
|
||||
const message = localize('proxyauth', "The proxy {0} requires authentication.", proxyUrl);
|
||||
const data = { title, message };
|
||||
const javascript = 'promptForCredentials(' + JSON.stringify(data) + ')';
|
||||
|
||||
const onWindowClose = () => cb('', '');
|
||||
win.on('close', onWindowClose);
|
||||
|
||||
win.setMenu(null);
|
||||
win.loadURL(url);
|
||||
win.webContents.executeJavaScript(javascript, true).then(({ username, password }: Credentials) => {
|
||||
cb(username, password);
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
const data = { title, message };
|
||||
win.webContents.send('vscode:openProxyAuthDialog', data);
|
||||
});
|
||||
win.webContents.on('ipc-message', (event, channel, credentials: Credentials) => {
|
||||
if (channel === 'vscode:proxyAuthResponse') {
|
||||
const { username, password } = credentials;
|
||||
cb(username, password);
|
||||
}
|
||||
win.removeListener('close', onWindowClose);
|
||||
win.close();
|
||||
});
|
||||
win.loadURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,8 +178,8 @@ class CodeMain {
|
||||
environmentService.extensionsPath,
|
||||
environmentService.nodeCachedDataDir,
|
||||
environmentService.logsPath,
|
||||
environmentService.globalStorageHome,
|
||||
environmentService.workspaceStorageHome,
|
||||
environmentService.globalStorageHome.fsPath,
|
||||
environmentService.workspaceStorageHome.fsPath,
|
||||
environmentService.backupHome.fsPath
|
||||
].map((path): undefined | Promise<void> => path ? mkdirp(path) : undefined));
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { parseArgs, OPTIONS, ParsedArgs } from 'vs/platform/environment/node/argv';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor } from 'vs/platform/windows/common/windows';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
import { ICodeWindow, IWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows';
|
||||
@@ -153,6 +153,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
// in case we are maximized or fullscreen, only show later after the call to maximize/fullscreen (see below)
|
||||
const isFullscreenOrMaximized = (this.windowState.mode === WindowMode.Maximized || this.windowState.mode === WindowMode.Fullscreen);
|
||||
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
|
||||
const options: BrowserWindowConstructorOptions = {
|
||||
width: this.windowState.width,
|
||||
height: this.windowState.height,
|
||||
@@ -169,7 +171,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
webviewTag: true,
|
||||
enableWebSQL: false,
|
||||
enableRemoteModule: false,
|
||||
nativeWindowOpen: true
|
||||
nativeWindowOpen: true,
|
||||
zoomFactor: zoomLevelToZoomFactor(windowConfig?.zoomLevel)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -182,8 +185,6 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
options.icon = path.join(this.environmentService.appRoot, 'resources/win32/code_150x150.png');
|
||||
}
|
||||
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
|
||||
if (isMacintosh && !this.useNativeFullScreen()) {
|
||||
options.fullscreenable = false; // enables simple fullscreen mode
|
||||
}
|
||||
@@ -214,6 +215,11 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
||||
this._win = new BrowserWindow(options);
|
||||
this._id = this._win.id;
|
||||
|
||||
// Open devtools if instructed from command line args
|
||||
if (this.environmentService.args['open-devtools'] === true) {
|
||||
this._win.webContents.openDevTools();
|
||||
}
|
||||
|
||||
if (isMacintosh && useCustomTitleStyle) {
|
||||
this._win.setSheetOffset(22); // offset dialogs by the height of the custom title bar if we have any
|
||||
}
|
||||
|
||||
+2
-39
@@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">
|
||||
content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
@@ -78,43 +78,6 @@
|
||||
</section>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
|
||||
function promptForCredentials(data) {
|
||||
return new Promise((c, e) => {
|
||||
const $title = document.getElementById('title');
|
||||
const $username = document.getElementById('username');
|
||||
const $password = document.getElementById('password');
|
||||
const $form = document.getElementById('form');
|
||||
const $cancel = document.getElementById('cancel');
|
||||
const $message = document.getElementById('message');
|
||||
|
||||
function submit() {
|
||||
c({ username: $username.value, password: $password.value });
|
||||
return false;
|
||||
};
|
||||
|
||||
function cancel() {
|
||||
c({ username: '', password: '' });
|
||||
return false;
|
||||
};
|
||||
|
||||
$form.addEventListener('submit', submit);
|
||||
$cancel.addEventListener('click', cancel);
|
||||
|
||||
document.body.addEventListener('keydown', function (e) {
|
||||
switch (e.keyCode) {
|
||||
case 27: e.preventDefault(); e.stopPropagation(); return cancel();
|
||||
case 13: e.preventDefault(); e.stopPropagation(); return submit();
|
||||
}
|
||||
});
|
||||
|
||||
$title.textContent = data.title;
|
||||
$message.textContent = data.message;
|
||||
$username.focus();
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
<script src="auth.js"></script>
|
||||
|
||||
</html>
|
||||
@@ -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.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const { ipcRenderer } = window.vscode;
|
||||
|
||||
function promptForCredentials(data) {
|
||||
return new Promise((c, e) => {
|
||||
const $title = document.getElementById('title');
|
||||
const $username = document.getElementById('username');
|
||||
const $password = document.getElementById('password');
|
||||
const $form = document.getElementById('form');
|
||||
const $cancel = document.getElementById('cancel');
|
||||
const $message = document.getElementById('message');
|
||||
|
||||
function submit() {
|
||||
c({ username: $username.value, password: $password.value });
|
||||
return false;
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
c({ username: '', password: '' });
|
||||
return false;
|
||||
}
|
||||
|
||||
$form.addEventListener('submit', submit);
|
||||
$cancel.addEventListener('click', cancel);
|
||||
|
||||
document.body.addEventListener('keydown', function (e) {
|
||||
switch (e.keyCode) {
|
||||
case 27: e.preventDefault(); e.stopPropagation(); return cancel();
|
||||
case 13: e.preventDefault(); e.stopPropagation(); return submit();
|
||||
}
|
||||
});
|
||||
|
||||
$title.textContent = data.title;
|
||||
$message.textContent = data.message;
|
||||
$username.focus();
|
||||
});
|
||||
}
|
||||
|
||||
ipcRenderer.on('vscode:openProxyAuthDialog', async (event, data) => {
|
||||
const response = await promptForCredentials(data);
|
||||
ipcRenderer.send('vscode:proxyAuthResponse', response);
|
||||
});
|
||||
+1
-1
@@ -319,7 +319,7 @@ var CSSBuildLoaderPlugin;
|
||||
global.cssInlinedResources = global.cssInlinedResources || [];
|
||||
var normalizedFSPath = fsPath.replace(/\\/g, '/');
|
||||
if (global.cssInlinedResources.indexOf(normalizedFSPath) >= 0) {
|
||||
console.warn('CSS INLINING IMAGE AT ' + fsPath + ' MORE THAN ONCE. CONSIDER CONSOLIDATING CSS RULES');
|
||||
// console.warn('CSS INLINING IMAGE AT ' + fsPath + ' MORE THAN ONCE. CONSIDER CONSOLIDATING CSS RULES');
|
||||
}
|
||||
global.cssInlinedResources.push(normalizedFSPath);
|
||||
var MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png';
|
||||
|
||||
@@ -11,10 +11,11 @@ import * as platform from 'vs/base/common/platform';
|
||||
import { CharWidthRequest, CharWidthRequestType, readCharWidths } from 'vs/editor/browser/config/charWidthReader';
|
||||
import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver';
|
||||
import { CommonEditorConfiguration, IEnvConfiguration } from 'vs/editor/common/config/commonEditorConfig';
|
||||
import { EditorOption, IEditorConstructionOptions, EditorFontLigatures } from 'vs/editor/common/config/editorOptions';
|
||||
import { EditorOption, EditorFontLigatures } from 'vs/editor/common/config/editorOptions';
|
||||
import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';
|
||||
import { IDimension } from 'vs/editor/common/editorCommon';
|
||||
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IEditorConstructionOptions } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
class CSSBasedConfigurationCache {
|
||||
|
||||
|
||||
@@ -336,6 +336,18 @@ export interface IEditorAriaOptions {
|
||||
role?: string;
|
||||
}
|
||||
|
||||
export interface IEditorConstructionOptions extends IEditorOptions {
|
||||
/**
|
||||
* The initial editor dimension (to avoid measuring the container).
|
||||
*/
|
||||
dimension?: editorCommon.IDimension;
|
||||
/**
|
||||
* Place overflow widgets inside an external DOM node.
|
||||
* Defaults to an internal DOM node.
|
||||
*/
|
||||
overflowWidgetsDomNode?: HTMLElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* A rich code editor.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@ import { IEditorContribution, IDiffEditorContribution } from 'vs/editor/common/e
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { MenuId, MenuRegistry, Action2 } from 'vs/platform/actions/common/actions';
|
||||
import { CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ContextKeyExpr, IContextKeyService, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConstructorSignature1, ServicesAccessor as InstantiationServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -339,6 +339,32 @@ export abstract class EditorAction extends EditorCommand {
|
||||
|
||||
//#endregion EditorAction
|
||||
|
||||
//#region EditorAction2
|
||||
|
||||
export abstract class EditorAction2 extends Action2 {
|
||||
|
||||
run(accessor: ServicesAccessor, ...args: any[]) {
|
||||
// Find the editor with text focus or active
|
||||
const codeEditorService = accessor.get(ICodeEditorService);
|
||||
const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();
|
||||
if (!editor) {
|
||||
// well, at least we tried...
|
||||
return;
|
||||
}
|
||||
// precondition does hold
|
||||
return editor.invokeWithinContext((editorAccessor) => {
|
||||
const kbService = editorAccessor.get(IContextKeyService);
|
||||
if (kbService.contextMatchesRules(withNullAsUndefined(this.desc.precondition))) {
|
||||
return this.runEditorCommand(editorAccessor, editor!, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
abstract runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, ...args: any[]): any;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
// --- Registration of commands and actions
|
||||
|
||||
export function registerLanguageCommand<Args extends { [n: string]: any; }>(id: string, handler: (accessor: ServicesAccessor, args: Args) => any) {
|
||||
|
||||
@@ -93,7 +93,8 @@ export class View extends ViewEventHandler {
|
||||
configuration: IConfiguration,
|
||||
themeService: IThemeService,
|
||||
model: IViewModel,
|
||||
userInputEvents: ViewUserInputEvents
|
||||
userInputEvents: ViewUserInputEvents,
|
||||
overflowWidgetsDomNode: HTMLElement | undefined
|
||||
) {
|
||||
super();
|
||||
this._selections = [new Selection(1, 1, 1, 1)];
|
||||
@@ -209,7 +210,12 @@ export class View extends ViewEventHandler {
|
||||
this._overflowGuardContainer.appendChild(this._overlayWidgets.getDomNode());
|
||||
this._overflowGuardContainer.appendChild(minimap.getDomNode());
|
||||
this.domNode.appendChild(this._overflowGuardContainer);
|
||||
this.domNode.appendChild(this._contentWidgets.overflowingContentWidgetsDomNode);
|
||||
|
||||
if (overflowWidgetsDomNode) {
|
||||
overflowWidgetsDomNode.appendChild(this._contentWidgets.overflowingContentWidgetsDomNode.domNode);
|
||||
} else {
|
||||
this.domNode.appendChild(this._contentWidgets.overflowingContentWidgetsDomNode);
|
||||
}
|
||||
|
||||
this._applyLayout();
|
||||
|
||||
@@ -317,6 +323,8 @@ export class View extends ViewEventHandler {
|
||||
this._renderAnimationFrame = null;
|
||||
}
|
||||
|
||||
this._contentWidgets.overflowingContentWidgetsDomNode.domNode.remove();
|
||||
|
||||
this._context.removeEventHandler(this);
|
||||
|
||||
this._viewLines.dispose();
|
||||
|
||||
@@ -21,7 +21,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
|
||||
import { ICommandDelegate } from 'vs/editor/browser/view/viewController';
|
||||
import { IContentWidgetData, IOverlayWidgetData, View } from 'vs/editor/browser/view/viewImpl';
|
||||
import { ViewUserInputEvents } from 'vs/editor/browser/view/viewUserInputEvents';
|
||||
import { ConfigurationChangedEvent, EditorLayoutInfo, IEditorOptions, EditorOption, IComputedEditorOptions, FindComputedEditorOptionValueById, IEditorConstructionOptions, filterValidationDecorations } from 'vs/editor/common/config/editorOptions';
|
||||
import { ConfigurationChangedEvent, EditorLayoutInfo, IEditorOptions, EditorOption, IComputedEditorOptions, FindComputedEditorOptionValueById, filterValidationDecorations } from 'vs/editor/common/config/editorOptions';
|
||||
import { Cursor } from 'vs/editor/common/controller/cursor';
|
||||
import { CursorColumns } from 'vs/editor/common/controller/cursorCommon';
|
||||
import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
@@ -208,6 +208,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
private readonly _telemetryData?: object;
|
||||
|
||||
private readonly _domElement: HTMLElement;
|
||||
private readonly _overflowWidgetsDomNode: HTMLElement | undefined;
|
||||
private readonly _id: number;
|
||||
private readonly _configuration: editorCommon.IConfiguration;
|
||||
|
||||
@@ -237,7 +238,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
|
||||
constructor(
|
||||
domElement: HTMLElement,
|
||||
options: IEditorConstructionOptions,
|
||||
options: editorBrowser.IEditorConstructionOptions,
|
||||
codeEditorWidgetOptions: ICodeEditorWidgetOptions,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@ICodeEditorService codeEditorService: ICodeEditorService,
|
||||
@@ -248,14 +249,17 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
@IAccessibilityService accessibilityService: IAccessibilityService
|
||||
) {
|
||||
super();
|
||||
|
||||
options = options || {};
|
||||
|
||||
this._domElement = domElement;
|
||||
this._overflowWidgetsDomNode = options.overflowWidgetsDomNode;
|
||||
this._id = (++EDITOR_ID);
|
||||
this._decorationTypeKeysToIds = {};
|
||||
this._decorationTypeSubtypes = {};
|
||||
this.isSimpleWidget = codeEditorWidgetOptions.isSimpleWidget || false;
|
||||
this._telemetryData = codeEditorWidgetOptions.telemetryData;
|
||||
|
||||
options = options || {};
|
||||
this._configuration = this._register(this._createConfiguration(options, accessibilityService));
|
||||
this._register(this._configuration.onDidChange((e) => {
|
||||
this._onDidChangeConfiguration.fire(e);
|
||||
@@ -324,7 +328,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
this._codeEditorService.addCodeEditor(this);
|
||||
}
|
||||
|
||||
protected _createConfiguration(options: IEditorConstructionOptions, accessibilityService: IAccessibilityService): editorCommon.IConfiguration {
|
||||
protected _createConfiguration(options: editorBrowser.IEditorConstructionOptions, accessibilityService: IAccessibilityService): editorCommon.IConfiguration {
|
||||
return new Configuration(this.isSimpleWidget, options, this._domElement, accessibilityService);
|
||||
}
|
||||
|
||||
@@ -1613,7 +1617,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
this._configuration,
|
||||
this._themeService,
|
||||
viewModel,
|
||||
viewUserInputEvents
|
||||
viewUserInputEvents,
|
||||
this._overflowWidgetsDomNode
|
||||
);
|
||||
|
||||
return [view, true];
|
||||
|
||||
@@ -208,6 +208,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
|
||||
private _ignoreTrimWhitespace: boolean;
|
||||
private _originalIsEditable: boolean;
|
||||
private _originalCodeLens: boolean;
|
||||
private _modifiedCodeLens: boolean;
|
||||
|
||||
private _renderSideBySide: boolean;
|
||||
private _maxComputationTime: number;
|
||||
@@ -286,6 +288,16 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
this._originalIsEditable = Boolean(options.originalEditable);
|
||||
}
|
||||
|
||||
this._originalCodeLens = false;
|
||||
if (typeof options.originalCodeLens !== 'undefined') {
|
||||
this._originalCodeLens = Boolean(options.originalCodeLens);
|
||||
}
|
||||
|
||||
this._modifiedCodeLens = false;
|
||||
if (typeof options.modifiedCodeLens !== 'undefined') {
|
||||
this._modifiedCodeLens = Boolean(options.modifiedCodeLens);
|
||||
}
|
||||
|
||||
this._updateDecorationsRunner = this._register(new RunOnceScheduler(() => this._updateDecorations(), 0));
|
||||
|
||||
this._containerDomElement = document.createElement('div');
|
||||
@@ -474,7 +486,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}
|
||||
|
||||
private _createLeftHandSideEditor(options: IDiffEditorOptions, instantiationService: IInstantiationService): CodeEditorWidget {
|
||||
const editor = this._createInnerEditor(instantiationService, this._originalDomNode, this._adjustOptionsForLeftHandSide(options, this._originalIsEditable));
|
||||
const editor = this._createInnerEditor(instantiationService, this._originalDomNode, this._adjustOptionsForLeftHandSide(options, this._originalIsEditable, this._originalCodeLens));
|
||||
|
||||
this._register(editor.onDidScrollChange((e) => {
|
||||
if (this._isHandlingScrollEvent) {
|
||||
@@ -507,7 +519,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
}
|
||||
|
||||
private _createRightHandSideEditor(options: IDiffEditorOptions, instantiationService: IInstantiationService): CodeEditorWidget {
|
||||
const editor = this._createInnerEditor(instantiationService, this._modifiedDomNode, this._adjustOptionsForRightHandSide(options));
|
||||
const editor = this._createInnerEditor(instantiationService, this._modifiedDomNode, this._adjustOptionsForRightHandSide(options, this._modifiedCodeLens));
|
||||
|
||||
this._register(editor.onDidScrollChange((e) => {
|
||||
if (this._isHandlingScrollEvent) {
|
||||
@@ -667,9 +679,15 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
if (typeof newOptions.originalEditable !== 'undefined') {
|
||||
this._originalIsEditable = Boolean(newOptions.originalEditable);
|
||||
}
|
||||
if (typeof newOptions.originalCodeLens !== 'undefined') {
|
||||
this._originalCodeLens = Boolean(newOptions.originalCodeLens);
|
||||
}
|
||||
if (typeof newOptions.modifiedCodeLens !== 'undefined') {
|
||||
this._modifiedCodeLens = Boolean(newOptions.modifiedCodeLens);
|
||||
}
|
||||
|
||||
this.modifiedEditor.updateOptions(this._adjustOptionsForRightHandSide(newOptions));
|
||||
this.originalEditor.updateOptions(this._adjustOptionsForLeftHandSide(newOptions, this._originalIsEditable));
|
||||
this.modifiedEditor.updateOptions(this._adjustOptionsForRightHandSide(newOptions, this._modifiedCodeLens));
|
||||
this.originalEditor.updateOptions(this._adjustOptionsForLeftHandSide(newOptions, this._originalIsEditable, this._originalCodeLens));
|
||||
|
||||
// enableSplitViewResizing
|
||||
if (typeof newOptions.enableSplitViewResizing !== 'undefined') {
|
||||
@@ -1065,15 +1083,21 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
||||
return clonedOptions;
|
||||
}
|
||||
|
||||
private _adjustOptionsForLeftHandSide(options: IDiffEditorOptions, isEditable: boolean): IEditorOptions {
|
||||
private _adjustOptionsForLeftHandSide(options: IDiffEditorOptions, isEditable: boolean, isCodeLensEnabled: boolean): IEditorOptions {
|
||||
let result = this._adjustOptionsForSubEditor(options);
|
||||
if (isCodeLensEnabled) {
|
||||
result.codeLens = true;
|
||||
}
|
||||
result.readOnly = !isEditable;
|
||||
result.extraEditorClassName = 'original-in-monaco-diff-editor';
|
||||
return result;
|
||||
}
|
||||
|
||||
private _adjustOptionsForRightHandSide(options: IDiffEditorOptions): IEditorOptions {
|
||||
private _adjustOptionsForRightHandSide(options: IDiffEditorOptions, isCodeLensEnabled: boolean): IEditorOptions {
|
||||
let result = this._adjustOptionsForSubEditor(options);
|
||||
if (isCodeLensEnabled) {
|
||||
result.codeLens = true;
|
||||
}
|
||||
result.revealHorizontalRightPadding = EditorOptions.revealHorizontalRightPadding.defaultValue + DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH;
|
||||
result.scrollbar!.verticalHasArrows = false;
|
||||
result.extraEditorClassName = 'modified-in-monaco-diff-editor';
|
||||
|
||||
@@ -541,6 +541,11 @@ const editorConfiguration: IConfigurationNode = {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
description: nls.localize('renderIndicators', "Controls whether the diff editor shows +/- indicators for added/removed changes.")
|
||||
},
|
||||
'diffEditor.codeLens': {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: nls.localize('codeLens', "Controls whether the editor shows CodeLens.")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,7 +11,6 @@ import { Constants } from 'vs/base/common/uint';
|
||||
import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/model/wordHelper';
|
||||
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IDimension } from 'vs/editor/common/editorCommon';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
|
||||
//#region typed options
|
||||
@@ -600,13 +599,6 @@ export interface IEditorOptions {
|
||||
showDeprecated?: boolean;
|
||||
}
|
||||
|
||||
export interface IEditorConstructionOptions extends IEditorOptions {
|
||||
/**
|
||||
* The initial editor dimension (to avoid measuring the container).
|
||||
*/
|
||||
dimension?: IDimension;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* The width of the minimap gutter, in pixels.
|
||||
@@ -647,12 +639,20 @@ export interface IDiffEditorOptions extends IEditorOptions {
|
||||
* Defaults to false.
|
||||
*/
|
||||
originalEditable?: boolean;
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
/**
|
||||
/** // {{SQL CARBON EDIT}}
|
||||
* Adding option to reverse coloring in diff editor
|
||||
*/
|
||||
reverse?: boolean;
|
||||
/**
|
||||
* Original editor should be have code lens enabled?
|
||||
* Defaults to false.
|
||||
*/
|
||||
originalCodeLens?: boolean;
|
||||
/**
|
||||
* Modified editor should be have code lens enabled?
|
||||
* Defaults to false.
|
||||
*/
|
||||
modifiedCodeLens?: boolean;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -1076,6 +1076,11 @@ export interface IEditorCommentsOptions {
|
||||
* Defaults to true.
|
||||
*/
|
||||
insertSpace?: boolean;
|
||||
/**
|
||||
* Ignore empty lines when inserting line comments.
|
||||
* Defaults to true.
|
||||
*/
|
||||
ignoreEmptyLines?: boolean;
|
||||
}
|
||||
|
||||
export type EditorCommentsOptions = Readonly<Required<IEditorCommentsOptions>>;
|
||||
@@ -1085,6 +1090,7 @@ class EditorComments extends BaseEditorOption<EditorOption.comments, EditorComme
|
||||
constructor() {
|
||||
const defaults: EditorCommentsOptions = {
|
||||
insertSpace: true,
|
||||
ignoreEmptyLines: true,
|
||||
};
|
||||
super(
|
||||
EditorOption.comments, 'comments', defaults,
|
||||
@@ -1094,6 +1100,11 @@ class EditorComments extends BaseEditorOption<EditorOption.comments, EditorComme
|
||||
default: defaults.insertSpace,
|
||||
description: nls.localize('comments.insertSpace', "Controls whether a space character is inserted when commenting.")
|
||||
},
|
||||
'editor.comments.ignoreEmptyLines': {
|
||||
type: 'boolean',
|
||||
default: defaults.ignoreEmptyLines,
|
||||
description: nls.localize('comments.ignoreEmptyLines', 'Controls if empty lines should be ignored with toggle, add or remove actions for line comments.')
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1105,6 +1116,7 @@ class EditorComments extends BaseEditorOption<EditorOption.comments, EditorComme
|
||||
const input = _input as IEditorCommentsOptions;
|
||||
return {
|
||||
insertSpace: EditorBooleanOption.boolean(input.insertSpace, this.defaultValue.insertSpace),
|
||||
ignoreEmptyLines: EditorBooleanOption.boolean(input.ignoreEmptyLines, this.defaultValue.ignoreEmptyLines),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ export class MirrorTextModel {
|
||||
protected _eol: string;
|
||||
protected _versionId: number;
|
||||
protected _lineStarts: PrefixSumComputer | null;
|
||||
private _cachedTextValue: string | null;
|
||||
|
||||
constructor(uri: URI, lines: string[], eol: string, versionId: number) {
|
||||
this._uri = uri;
|
||||
@@ -38,6 +39,7 @@ export class MirrorTextModel {
|
||||
this._eol = eol;
|
||||
this._versionId = versionId;
|
||||
this._lineStarts = null;
|
||||
this._cachedTextValue = null;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
@@ -49,7 +51,10 @@ export class MirrorTextModel {
|
||||
}
|
||||
|
||||
getText(): string {
|
||||
return this._lines.join(this._eol);
|
||||
if (this._cachedTextValue === null) {
|
||||
this._cachedTextValue = this._lines.join(this._eol);
|
||||
}
|
||||
return this._cachedTextValue;
|
||||
}
|
||||
|
||||
onEvents(e: IModelChangedEvent): void {
|
||||
@@ -66,6 +71,7 @@ export class MirrorTextModel {
|
||||
}
|
||||
|
||||
this._versionId = e.versionId;
|
||||
this._cachedTextValue = null;
|
||||
}
|
||||
|
||||
protected _ensureLineStarts(): void {
|
||||
|
||||
@@ -239,7 +239,7 @@ class PieceTreeSearchCache {
|
||||
this._cache.push(nodePosition);
|
||||
}
|
||||
|
||||
public valdiate(offset: number) {
|
||||
public validate(offset: number) {
|
||||
let hasInvalidVal = false;
|
||||
let tmp: Array<CacheEntry | null> = this._cache;
|
||||
for (let i = 0; i < tmp.length; i++) {
|
||||
@@ -838,7 +838,7 @@ export class PieceTreeBase {
|
||||
|
||||
if (nodeStartOffset === offset) {
|
||||
this.insertContentToNodeLeft(value, node);
|
||||
this._searchCache.valdiate(offset);
|
||||
this._searchCache.validate(offset);
|
||||
} else if (nodeStartOffset + node.piece.length > offset) {
|
||||
// we are inserting into the middle of a node.
|
||||
let nodesToDel: TreeNode[] = [];
|
||||
@@ -938,7 +938,7 @@ export class PieceTreeBase {
|
||||
return;
|
||||
}
|
||||
this.deleteNodeHead(startNode, endSplitPosInBuffer);
|
||||
this._searchCache.valdiate(offset);
|
||||
this._searchCache.validate(offset);
|
||||
this.validateCRLFWithPrevNode(startNode);
|
||||
this.computeBufferMetadata();
|
||||
return;
|
||||
@@ -961,7 +961,7 @@ export class PieceTreeBase {
|
||||
|
||||
let startSplitPosInBuffer = this.positionInBuffer(startNode, startPosition.remainder);
|
||||
this.deleteNodeTail(startNode, startSplitPosInBuffer);
|
||||
this._searchCache.valdiate(offset);
|
||||
this._searchCache.validate(offset);
|
||||
if (startNode.piece.length === 0) {
|
||||
nodesToDel.push(startNode);
|
||||
}
|
||||
@@ -1225,14 +1225,14 @@ export class PieceTreeBase {
|
||||
let cache = this._searchCache.get2(lineNumber);
|
||||
if (cache) {
|
||||
x = cache.node;
|
||||
let prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);
|
||||
let prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber - 1);
|
||||
let buffer = this._buffers[x.piece.bufferIndex].buffer;
|
||||
let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
||||
if (cache.nodeStartLineNumber + x.piece.lineFeedCnt === lineNumber) {
|
||||
ret = buffer.substring(startOffset + prevAccumualtedValue, startOffset + x.piece.length);
|
||||
ret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);
|
||||
} else {
|
||||
let accumualtedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);
|
||||
return buffer.substring(startOffset + prevAccumualtedValue, startOffset + accumualtedValue - endOffset);
|
||||
let accumulatedValue = this.getAccumulatedValue(x, lineNumber - cache.nodeStartLineNumber);
|
||||
return buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);
|
||||
}
|
||||
} else {
|
||||
let nodeStartOffset = 0;
|
||||
@@ -1241,8 +1241,8 @@ export class PieceTreeBase {
|
||||
if (x.left !== SENTINEL && x.lf_left >= lineNumber - 1) {
|
||||
x = x.left;
|
||||
} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {
|
||||
let prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
||||
let accumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);
|
||||
let prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
||||
let accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);
|
||||
let buffer = this._buffers[x.piece.bufferIndex].buffer;
|
||||
let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
||||
nodeStartOffset += x.size_left;
|
||||
@@ -1252,13 +1252,13 @@ export class PieceTreeBase {
|
||||
nodeStartLineNumber: originalLineNumber - (lineNumber - 1 - x.lf_left)
|
||||
});
|
||||
|
||||
return buffer.substring(startOffset + prevAccumualtedValue, startOffset + accumualtedValue - endOffset);
|
||||
return buffer.substring(startOffset + prevAccumulatedValue, startOffset + accumulatedValue - endOffset);
|
||||
} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {
|
||||
let prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
||||
let prevAccumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
||||
let buffer = this._buffers[x.piece.bufferIndex].buffer;
|
||||
let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
||||
|
||||
ret = buffer.substring(startOffset + prevAccumualtedValue, startOffset + x.piece.length);
|
||||
ret = buffer.substring(startOffset + prevAccumulatedValue, startOffset + x.piece.length);
|
||||
break;
|
||||
} else {
|
||||
lineNumber -= x.lf_left + x.piece.lineFeedCnt;
|
||||
@@ -1274,10 +1274,10 @@ export class PieceTreeBase {
|
||||
let buffer = this._buffers[x.piece.bufferIndex].buffer;
|
||||
|
||||
if (x.piece.lineFeedCnt > 0) {
|
||||
let accumualtedValue = this.getAccumulatedValue(x, 0);
|
||||
let accumulatedValue = this.getAccumulatedValue(x, 0);
|
||||
let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
||||
|
||||
ret += buffer.substring(startOffset, startOffset + accumualtedValue - endOffset);
|
||||
ret += buffer.substring(startOffset, startOffset + accumulatedValue - endOffset);
|
||||
return ret;
|
||||
} else {
|
||||
let startOffset = this.offsetInBuffer(x.piece.bufferIndex, x.piece.start);
|
||||
@@ -1304,7 +1304,7 @@ export class PieceTreeBase {
|
||||
|
||||
this._lineCnt = lfCnt;
|
||||
this._length = len;
|
||||
this._searchCache.valdiate(this._length);
|
||||
this._searchCache.validate(this._length);
|
||||
}
|
||||
|
||||
// #region node operations
|
||||
@@ -1504,12 +1504,12 @@ export class PieceTreeBase {
|
||||
x = x.left;
|
||||
} else if (x.lf_left + x.piece.lineFeedCnt > lineNumber - 1) {
|
||||
let prevAccumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 2);
|
||||
let accumualtedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);
|
||||
let accumulatedValue = this.getAccumulatedValue(x, lineNumber - x.lf_left - 1);
|
||||
nodeStartOffset += x.size_left;
|
||||
|
||||
return {
|
||||
node: x,
|
||||
remainder: Math.min(prevAccumualtedValue + column - 1, accumualtedValue),
|
||||
remainder: Math.min(prevAccumualtedValue + column - 1, accumulatedValue),
|
||||
nodeStartOffset
|
||||
};
|
||||
} else if (x.lf_left + x.piece.lineFeedCnt === lineNumber - 1) {
|
||||
@@ -1536,11 +1536,11 @@ export class PieceTreeBase {
|
||||
while (x !== SENTINEL) {
|
||||
|
||||
if (x.piece.lineFeedCnt > 0) {
|
||||
let accumualtedValue = this.getAccumulatedValue(x, 0);
|
||||
let accumulatedValue = this.getAccumulatedValue(x, 0);
|
||||
let nodeStartOffset = this.offsetOfNode(x);
|
||||
return {
|
||||
node: x,
|
||||
remainder: Math.min(column - 1, accumualtedValue),
|
||||
remainder: Math.min(column - 1, accumulatedValue),
|
||||
nodeStartOffset
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -30,7 +30,6 @@ import { NULL_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/nullMode';
|
||||
import { ignoreBracketsInToken } from 'vs/editor/common/modes/supports';
|
||||
import { BracketsUtils, RichEditBracket, RichEditBrackets } from 'vs/editor/common/modes/supports/richEditBrackets';
|
||||
import { ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
import { VSBufferReadableStream, VSBuffer } from 'vs/base/common/buffer';
|
||||
import { TokensStore, MultilineTokens, countEOL, MultilineTokens2, TokensStore2 } from 'vs/editor/common/model/tokensStore';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
@@ -3185,8 +3184,8 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions {
|
||||
this.stickiness = options.stickiness || model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges;
|
||||
this.zIndex = options.zIndex || 0;
|
||||
this.className = options.className ? cleanClassName(options.className) : null;
|
||||
this.hoverMessage = withUndefinedAsNull(options.hoverMessage);
|
||||
this.glyphMarginHoverMessage = withUndefinedAsNull(options.glyphMarginHoverMessage);
|
||||
this.hoverMessage = options.hoverMessage || null;
|
||||
this.glyphMarginHoverMessage = options.glyphMarginHoverMessage || null;
|
||||
this.isWholeLine = options.isWholeLine || false;
|
||||
this.showIfCollapsed = options.showIfCollapsed || false;
|
||||
this.collapseOnReplaceEdit = options.collapseOnReplaceEdit || false;
|
||||
|
||||
@@ -1413,19 +1413,27 @@ export interface AuthenticationSession {
|
||||
id: string;
|
||||
accessToken: string;
|
||||
account: {
|
||||
displayName: string;
|
||||
label: string;
|
||||
id: string;
|
||||
}
|
||||
scopes: string[];
|
||||
scopes: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface AuthenticationSessionsChangeEvent {
|
||||
added: string[];
|
||||
removed: string[];
|
||||
changed: string[];
|
||||
added: ReadonlyArray<string>;
|
||||
removed: ReadonlyArray<string>;
|
||||
changed: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface AuthenticationProviderInformation {
|
||||
id: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface Command {
|
||||
|
||||
@@ -7,8 +7,7 @@ import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ColorId, ITokenizationRegistry, ITokenizationSupport, ITokenizationSupportChangedEvent } from 'vs/editor/common/modes';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
import { toArray } from 'vs/base/common/arrays';
|
||||
|
||||
export class TokenizationRegistryImpl implements ITokenizationRegistry {
|
||||
|
||||
@@ -77,13 +76,13 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry {
|
||||
}
|
||||
|
||||
public get(language: string): ITokenizationSupport | null {
|
||||
return withUndefinedAsNull(this._map.get(language));
|
||||
return (this._map.get(language) || null);
|
||||
}
|
||||
|
||||
public setColorMap(colorMap: Color[]): void {
|
||||
this._colorMap = colorMap;
|
||||
this._onDidChange.fire({
|
||||
changedLanguages: keys(this._map),
|
||||
changedLanguages: toArray(this._map.keys()),
|
||||
changedColorMap: true
|
||||
});
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import { NULL_LANGUAGE_IDENTIFIER, NULL_MODE_ID } from 'vs/editor/common/modes/n
|
||||
import { ILanguageExtensionPoint } from 'vs/editor/common/services/modeService';
|
||||
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
|
||||
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
@@ -268,7 +267,7 @@ export class LanguagesRegistry extends Disposable {
|
||||
return null;
|
||||
}
|
||||
const language = this._languages[modeId];
|
||||
return withUndefinedAsNull(language.mimetypes[0]);
|
||||
return (language.mimetypes[0] || null);
|
||||
}
|
||||
|
||||
public extractModeIds(commaSeparatedMimetypesOrCommaSeparatedIds: string | undefined): string[] {
|
||||
|
||||
@@ -12,11 +12,9 @@ import { themeColorFromId, ThemeColor } from 'vs/platform/theme/common/themeServ
|
||||
import { overviewRulerWarning, overviewRulerInfo, overviewRulerError } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
import { minimapWarning, minimapError } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
|
||||
@@ -33,7 +31,7 @@ class MarkerDecorations extends Disposable {
|
||||
) {
|
||||
super();
|
||||
this._register(toDisposable(() => {
|
||||
this.model.deltaDecorations(keys(this._markersData), []);
|
||||
this.model.deltaDecorations([...this._markersData.keys()], []);
|
||||
this._markersData.clear();
|
||||
}));
|
||||
}
|
||||
@@ -43,7 +41,7 @@ class MarkerDecorations extends Disposable {
|
||||
}
|
||||
|
||||
public update(markers: IMarker[], newDecorations: IModelDeltaDecoration[]): boolean {
|
||||
const oldIds = keys(this._markersData);
|
||||
const oldIds = [...this._markersData.keys()];
|
||||
this._markersData.clear();
|
||||
const ids = this.model.deltaDecorations(oldIds, newDecorations);
|
||||
for (let index = 0; index < ids.length; index++) {
|
||||
@@ -96,7 +94,7 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
|
||||
|
||||
getMarker(model: ITextModel, decoration: IModelDecoration): IMarker | null {
|
||||
const markerDecorations = this._markerDecorations.get(MODEL_ID(model.uri));
|
||||
return markerDecorations ? withUndefinedAsNull(markerDecorations.getMarker(decoration)) : null;
|
||||
return markerDecorations ? (markerDecorations.getMarker(decoration) || null) : null;
|
||||
}
|
||||
|
||||
getLiveMarkers(model: ITextModel): [Range, IMarker][] {
|
||||
|
||||
@@ -36,7 +36,13 @@ abstract class CommentLineAction extends EditorAction {
|
||||
const commentsOptions = editor.getOption(EditorOption.comments);
|
||||
|
||||
for (const selection of selections) {
|
||||
commands.push(new LineCommentCommand(selection, modelOptions.tabSize, this._type, commentsOptions.insertSpace));
|
||||
commands.push(new LineCommentCommand(
|
||||
selection,
|
||||
modelOptions.tabSize,
|
||||
this._type,
|
||||
commentsOptions.insertSpace,
|
||||
commentsOptions.ignoreEmptyLines
|
||||
));
|
||||
}
|
||||
|
||||
editor.pushUndoStop();
|
||||
|
||||
@@ -53,11 +53,18 @@ export class LineCommentCommand implements ICommand {
|
||||
private readonly _tabSize: number;
|
||||
private readonly _type: Type;
|
||||
private readonly _insertSpace: boolean;
|
||||
private readonly _ignoreEmptyLines: boolean;
|
||||
private _selectionId: string | null;
|
||||
private _deltaColumn: number;
|
||||
private _moveEndPositionDown: boolean;
|
||||
|
||||
constructor(selection: Selection, tabSize: number, type: Type, insertSpace: boolean) {
|
||||
constructor(
|
||||
selection: Selection,
|
||||
tabSize: number,
|
||||
type: Type,
|
||||
insertSpace: boolean,
|
||||
ignoreEmptyLines: boolean
|
||||
) {
|
||||
this._selection = selection;
|
||||
this._tabSize = tabSize;
|
||||
this._type = type;
|
||||
@@ -65,6 +72,7 @@ export class LineCommentCommand implements ICommand {
|
||||
this._selectionId = null;
|
||||
this._deltaColumn = 0;
|
||||
this._moveEndPositionDown = false;
|
||||
this._ignoreEmptyLines = ignoreEmptyLines;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +108,7 @@ export class LineCommentCommand implements ICommand {
|
||||
* Analyze lines and decide which lines are relevant and what the toggle should do.
|
||||
* Also, build up several offsets and lengths useful in the generation of editor operations.
|
||||
*/
|
||||
public static _analyzeLines(type: Type, insertSpace: boolean, model: ISimpleModel, lines: ILinePreflightData[], startLineNumber: number): IPreflightData {
|
||||
public static _analyzeLines(type: Type, insertSpace: boolean, model: ISimpleModel, lines: ILinePreflightData[], startLineNumber: number, ignoreEmptyLines: boolean): IPreflightData {
|
||||
let onlyWhitespaceLines = true;
|
||||
|
||||
let shouldRemoveComments: boolean;
|
||||
@@ -121,13 +129,7 @@ export class LineCommentCommand implements ICommand {
|
||||
|
||||
if (lineContentStartOffset === -1) {
|
||||
// Empty or whitespace only line
|
||||
if (type === Type.Toggle) {
|
||||
lineData.ignore = true;
|
||||
} else if (type === Type.ForceAdd) {
|
||||
lineData.ignore = true;
|
||||
} else {
|
||||
lineData.ignore = true;
|
||||
}
|
||||
lineData.ignore = ignoreEmptyLines;
|
||||
lineData.commentStrOffset = lineContent.length;
|
||||
continue;
|
||||
}
|
||||
@@ -176,7 +178,7 @@ export class LineCommentCommand implements ICommand {
|
||||
/**
|
||||
* Analyze all lines and decide exactly what to do => not supported | insert line comments | remove line comments
|
||||
*/
|
||||
public static _gatherPreflightData(type: Type, insertSpace: boolean, model: ITextModel, startLineNumber: number, endLineNumber: number): IPreflightData {
|
||||
public static _gatherPreflightData(type: Type, insertSpace: boolean, model: ITextModel, startLineNumber: number, endLineNumber: number, ignoreEmptyLines: boolean): IPreflightData {
|
||||
const lines = LineCommentCommand._gatherPreflightCommentStrings(model, startLineNumber, endLineNumber);
|
||||
if (lines === null) {
|
||||
return {
|
||||
@@ -184,7 +186,7 @@ export class LineCommentCommand implements ICommand {
|
||||
};
|
||||
}
|
||||
|
||||
return LineCommentCommand._analyzeLines(type, insertSpace, model, lines, startLineNumber);
|
||||
return LineCommentCommand._analyzeLines(type, insertSpace, model, lines, startLineNumber, ignoreEmptyLines);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,7 +328,15 @@ export class LineCommentCommand implements ICommand {
|
||||
s = s.setEndPosition(s.endLineNumber - 1, model.getLineMaxColumn(s.endLineNumber - 1));
|
||||
}
|
||||
|
||||
const data = LineCommentCommand._gatherPreflightData(this._type, this._insertSpace, model, s.startLineNumber, s.endLineNumber);
|
||||
const data = LineCommentCommand._gatherPreflightData(
|
||||
this._type,
|
||||
this._insertSpace,
|
||||
model,
|
||||
s.startLineNumber,
|
||||
s.endLineNumber,
|
||||
this._ignoreEmptyLines
|
||||
);
|
||||
|
||||
if (data.supported) {
|
||||
return this._executeLineComments(model, builder, data, s);
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ suite('Editor Contrib - Line Comment Command', () => {
|
||||
|
||||
function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
|
||||
let mode = new CommentMode({ lineComment: '!@#', blockComment: ['<!@#', '#@!>'] });
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, true), expectedLines, expectedSelection);
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, true, true), expectedLines, expectedSelection);
|
||||
mode.dispose();
|
||||
}
|
||||
|
||||
function testAddLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
|
||||
let mode = new CommentMode({ lineComment: '!@#', blockComment: ['<!@#', '#@!>'] });
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.ForceAdd, true), expectedLines, expectedSelection);
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.ForceAdd, true, true), expectedLines, expectedSelection);
|
||||
mode.dispose();
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ suite('Editor Contrib - Line Comment Command', () => {
|
||||
test('case insensitive', function () {
|
||||
function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
|
||||
let mode = new CommentMode({ lineComment: 'rem' });
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, true), expectedLines, expectedSelection);
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, true, true), expectedLines, expectedSelection);
|
||||
mode.dispose();
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ suite('Editor Contrib - Line Comment Command', () => {
|
||||
' ',
|
||||
' c',
|
||||
'\t\td'
|
||||
]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1);
|
||||
]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1, true);
|
||||
if (!r.supported) {
|
||||
throw new Error(`unexpected`);
|
||||
}
|
||||
@@ -122,7 +122,7 @@ suite('Editor Contrib - Line Comment Command', () => {
|
||||
' rem ',
|
||||
' !@# c',
|
||||
'\t\t!@#d'
|
||||
]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1);
|
||||
]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1, true);
|
||||
if (!r.supported) {
|
||||
throw new Error(`unexpected`);
|
||||
}
|
||||
@@ -631,7 +631,7 @@ suite('Editor Contrib - Line Comment Command', () => {
|
||||
test('insertSpace false', () => {
|
||||
function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
|
||||
let mode = new CommentMode({ lineComment: '!@#' });
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, false), expectedLines, expectedSelection);
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, false, true), expectedLines, expectedSelection);
|
||||
mode.dispose();
|
||||
}
|
||||
|
||||
@@ -650,7 +650,7 @@ suite('Editor Contrib - Line Comment Command', () => {
|
||||
test('insertSpace false does not remove space', () => {
|
||||
function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
|
||||
let mode = new CommentMode({ lineComment: '!@#' });
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, false), expectedLines, expectedSelection);
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, false, true), expectedLines, expectedSelection);
|
||||
mode.dispose();
|
||||
}
|
||||
|
||||
@@ -665,13 +665,104 @@ suite('Editor Contrib - Line Comment Command', () => {
|
||||
new Selection(1, 1, 1, 1)
|
||||
);
|
||||
});
|
||||
|
||||
suite('ignoreEmptyLines false', () => {
|
||||
function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
|
||||
let mode = new CommentMode({ lineComment: '!@#', blockComment: ['<!@#', '#@!>'] });
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, true, false), expectedLines, expectedSelection);
|
||||
mode.dispose();
|
||||
}
|
||||
|
||||
test('does not ignore whitespace lines', () => {
|
||||
testLineCommentCommand(
|
||||
[
|
||||
'\tsome text',
|
||||
'\t ',
|
||||
'',
|
||||
'\tsome more text'
|
||||
],
|
||||
new Selection(4, 2, 1, 1),
|
||||
[
|
||||
'!@# \tsome text',
|
||||
'!@# \t ',
|
||||
'!@# ',
|
||||
'!@# \tsome more text'
|
||||
],
|
||||
new Selection(4, 6, 1, 5)
|
||||
);
|
||||
});
|
||||
|
||||
test('removes its own', function () {
|
||||
testLineCommentCommand(
|
||||
[
|
||||
'\t!@# some text',
|
||||
'\t ',
|
||||
'\t\t!@# some more text'
|
||||
],
|
||||
new Selection(3, 2, 1, 1),
|
||||
[
|
||||
'\tsome text',
|
||||
'\t ',
|
||||
'\t\tsome more text'
|
||||
],
|
||||
new Selection(3, 2, 1, 1)
|
||||
);
|
||||
});
|
||||
|
||||
test('works in only whitespace', function () {
|
||||
testLineCommentCommand(
|
||||
[
|
||||
'\t ',
|
||||
'\t',
|
||||
'\t\tsome more text'
|
||||
],
|
||||
new Selection(3, 1, 1, 1),
|
||||
[
|
||||
'\t!@# ',
|
||||
'\t!@# ',
|
||||
'\t\tsome more text'
|
||||
],
|
||||
new Selection(3, 1, 1, 1)
|
||||
);
|
||||
});
|
||||
|
||||
test('comments single line', function () {
|
||||
testLineCommentCommand(
|
||||
[
|
||||
'some text',
|
||||
'\tsome more text'
|
||||
],
|
||||
new Selection(1, 1, 1, 1),
|
||||
[
|
||||
'!@# some text',
|
||||
'\tsome more text'
|
||||
],
|
||||
new Selection(1, 5, 1, 5)
|
||||
);
|
||||
});
|
||||
|
||||
test('detects indentation', function () {
|
||||
testLineCommentCommand(
|
||||
[
|
||||
'\tsome text',
|
||||
'\tsome more text'
|
||||
],
|
||||
new Selection(2, 2, 1, 1),
|
||||
[
|
||||
'\t!@# some text',
|
||||
'\t!@# some more text'
|
||||
],
|
||||
new Selection(2, 2, 1, 1)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('Editor Contrib - Line Comment As Block Comment', () => {
|
||||
|
||||
function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
|
||||
let mode = new CommentMode({ lineComment: '', blockComment: ['(', ')'] });
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, true), expectedLines, expectedSelection);
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, true, true), expectedLines, expectedSelection);
|
||||
mode.dispose();
|
||||
}
|
||||
|
||||
@@ -782,7 +873,7 @@ suite('Editor Contrib - Line Comment As Block Comment', () => {
|
||||
suite('Editor Contrib - Line Comment As Block Comment 2', () => {
|
||||
function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
|
||||
let mode = new CommentMode({ lineComment: null, blockComment: ['<!@#', '#@!>'] });
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, true), expectedLines, expectedSelection);
|
||||
testCommand(lines, mode.getLanguageIdentifier(), selection, (sel) => new LineCommentCommand(sel, 4, Type.Toggle, true, true), expectedLines, expectedSelection);
|
||||
mode.dispose();
|
||||
}
|
||||
|
||||
@@ -1023,7 +1114,7 @@ suite('Editor Contrib - Line Comment in mixed modes', () => {
|
||||
lines,
|
||||
outerMode.getLanguageIdentifier(),
|
||||
selection,
|
||||
(sel) => new LineCommentCommand(sel, 4, Type.Toggle, true),
|
||||
(sel) => new LineCommentCommand(sel, 4, Type.Toggle, true, true),
|
||||
expectedLines,
|
||||
expectedSelection,
|
||||
true
|
||||
|
||||
@@ -280,6 +280,12 @@ export class CommonFindController extends Disposable implements IEditorContribut
|
||||
|
||||
if (!stateChanges.searchString && opts.seedSearchStringFromGlobalClipboard) {
|
||||
let selectionSearchString = await this.getGlobalBufferTerm();
|
||||
|
||||
if (!this._editor.hasModel()) {
|
||||
// the editor has lost its model in the meantime
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectionSearchString) {
|
||||
stateChanges.searchString = selectionSearchString;
|
||||
}
|
||||
@@ -364,13 +370,14 @@ export class CommonFindController extends Disposable implements IEditorContribut
|
||||
return '';
|
||||
}
|
||||
|
||||
public async setGlobalBufferTerm(text: string) {
|
||||
public setGlobalBufferTerm(text: string): void {
|
||||
if (this._editor.getOption(EditorOption.find).globalFindClipboard
|
||||
&& this._clipboardService
|
||||
&& this._editor.hasModel()
|
||||
&& !this._editor.getModel().isTooLargeForSyncing()
|
||||
) {
|
||||
await this._clipboardService.writeFindText(text);
|
||||
// intentionally not awaited
|
||||
this._clipboardService.writeFindText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -424,10 +431,12 @@ export class FindController extends CommonFindController implements IFindControl
|
||||
|
||||
await super._start(opts);
|
||||
|
||||
if (opts.shouldFocus === FindStartFocusAction.FocusReplaceInput) {
|
||||
this._widget!.focusReplaceInput();
|
||||
} else if (opts.shouldFocus === FindStartFocusAction.FocusFindInput) {
|
||||
this._widget!.focusFindInput();
|
||||
if (this._widget) {
|
||||
if (opts.shouldFocus === FindStartFocusAction.FocusReplaceInput) {
|
||||
this._widget.focusReplaceInput();
|
||||
} else if (opts.shouldFocus === FindStartFocusAction.FocusFindInput) {
|
||||
this._widget.focusFindInput();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,10 +479,10 @@ export class StartFindAction extends EditorAction {
|
||||
});
|
||||
}
|
||||
|
||||
public run(accessor: ServicesAccessor | null, editor: ICodeEditor): void {
|
||||
public async run(accessor: ServicesAccessor | null, editor: ICodeEditor): Promise<void> {
|
||||
let controller = CommonFindController.get(editor);
|
||||
if (controller) {
|
||||
controller.start({
|
||||
await controller.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: editor.getOption(EditorOption.find).seedSearchStringFromSelection,
|
||||
seedSearchStringFromGlobalClipboard: editor.getOption(EditorOption.find).globalFindClipboard,
|
||||
@@ -508,7 +517,7 @@ export class StartFindWithSelectionAction extends EditorAction {
|
||||
public async run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
|
||||
let controller = CommonFindController.get(editor);
|
||||
if (controller) {
|
||||
controller.start({
|
||||
await controller.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: true,
|
||||
seedSearchStringFromGlobalClipboard: false,
|
||||
@@ -518,15 +527,15 @@ export class StartFindWithSelectionAction extends EditorAction {
|
||||
loop: editor.getOption(EditorOption.find).loop
|
||||
});
|
||||
|
||||
return controller.setGlobalBufferTerm(controller.getState().searchString);
|
||||
controller.setGlobalBufferTerm(controller.getState().searchString);
|
||||
}
|
||||
}
|
||||
}
|
||||
export abstract class MatchFindAction extends EditorAction {
|
||||
public run(accessor: ServicesAccessor | null, editor: ICodeEditor): void {
|
||||
public async run(accessor: ServicesAccessor | null, editor: ICodeEditor): Promise<void> {
|
||||
let controller = CommonFindController.get(editor);
|
||||
if (controller && !this._run(controller)) {
|
||||
controller.start({
|
||||
await controller.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: (controller.getState().searchString.length === 0) && editor.getOption(EditorOption.find).seedSearchStringFromSelection,
|
||||
seedSearchStringFromGlobalClipboard: true,
|
||||
@@ -629,7 +638,7 @@ export class PreviousMatchFindAction2 extends MatchFindAction {
|
||||
}
|
||||
|
||||
export abstract class SelectionMatchFindAction extends EditorAction {
|
||||
public run(accessor: ServicesAccessor | null, editor: ICodeEditor): void {
|
||||
public async run(accessor: ServicesAccessor | null, editor: ICodeEditor): Promise<void> {
|
||||
let controller = CommonFindController.get(editor);
|
||||
if (!controller) {
|
||||
return;
|
||||
@@ -639,7 +648,7 @@ export abstract class SelectionMatchFindAction extends EditorAction {
|
||||
controller.setSearchString(selectionSearchString);
|
||||
}
|
||||
if (!this._run(controller)) {
|
||||
controller.start({
|
||||
await controller.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: editor.getOption(EditorOption.find).seedSearchStringFromSelection,
|
||||
seedSearchStringFromGlobalClipboard: false,
|
||||
@@ -720,7 +729,7 @@ export class StartFindReplaceAction extends EditorAction {
|
||||
});
|
||||
}
|
||||
|
||||
public run(accessor: ServicesAccessor | null, editor: ICodeEditor): void {
|
||||
public async run(accessor: ServicesAccessor | null, editor: ICodeEditor): Promise<void> {
|
||||
if (!editor.hasModel() || editor.getOption(EditorOption.readOnly)) {
|
||||
return;
|
||||
}
|
||||
@@ -745,7 +754,7 @@ export class StartFindReplaceAction extends EditorAction {
|
||||
|
||||
|
||||
if (controller) {
|
||||
controller.start({
|
||||
await controller.start({
|
||||
forceRevealReplace: true,
|
||||
seedSearchStringFromSelection: seedSearchStringFromSelection,
|
||||
seedSearchStringFromGlobalClipboard: editor.getOption(EditorOption.find).seedSearchStringFromSelection,
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { CommonFindController, FindStartFocusAction, IFindStartOptions, NextMatchFindAction, NextSelectionMatchFindAction, StartFindAction, StartFindReplaceAction } from 'vs/editor/contrib/find/findController';
|
||||
import { CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel';
|
||||
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { withAsyncTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
@@ -55,7 +55,7 @@ function fromSelection(slc: Selection): number[] {
|
||||
return [slc.startLineNumber, slc.startColumn, slc.endLineNumber, slc.endColumn];
|
||||
}
|
||||
|
||||
suite.skip('FindController', () => {
|
||||
suite.skip('FindController', async () => {
|
||||
let queryState: { [key: string]: any; } = {};
|
||||
let clipboardState = '';
|
||||
let serviceCollection = new ServiceCollection();
|
||||
@@ -77,13 +77,13 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
}
|
||||
|
||||
/* test('stores to the global clipboard buffer on start find action', () => {
|
||||
withTestCodeEditor([
|
||||
/* test('stores to the global clipboard buffer on start find action', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'ABC',
|
||||
'ABC',
|
||||
'XYZ',
|
||||
'ABC'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
if (!platform.isMacintosh) {
|
||||
assert.ok(true);
|
||||
@@ -101,13 +101,13 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('reads from the global clipboard buffer on next find action if buffer exists', () => {
|
||||
withTestCodeEditor([
|
||||
test('reads from the global clipboard buffer on next find action if buffer exists', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'ABC',
|
||||
'ABC',
|
||||
'XYZ',
|
||||
'ABC'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = 'ABC';
|
||||
|
||||
if (!platform.isMacintosh) {
|
||||
@@ -128,13 +128,13 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('writes to the global clipboard buffer when text changes', () => {
|
||||
withTestCodeEditor([
|
||||
test('writes to the global clipboard buffer when text changes', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'ABC',
|
||||
'ABC',
|
||||
'XYZ',
|
||||
'ABC'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
if (!platform.isMacintosh) {
|
||||
assert.ok(true);
|
||||
@@ -152,13 +152,13 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
}); */
|
||||
|
||||
test('issue #1857: F3, Find Next, acts like "Find Under Cursor"', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #1857: F3, Find Next, acts like "Find Under Cursor"', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'ABC',
|
||||
'ABC',
|
||||
'XYZ',
|
||||
'ABC'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
// The cursor is at the very top, of the file, at the first ABC
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
@@ -167,7 +167,7 @@ suite.skip('FindController', () => {
|
||||
let nextMatchFindAction = new NextMatchFindAction();
|
||||
|
||||
// I hit Ctrl+F to show the Find dialog
|
||||
startFindAction.run(null, editor);
|
||||
await startFindAction.run(null, editor);
|
||||
|
||||
// I type ABC.
|
||||
findState.change({ searchString: 'A' }, true);
|
||||
@@ -201,7 +201,7 @@ suite.skip('FindController', () => {
|
||||
assert.deepEqual(fromSelection(editor.getSelection()!), [1, 4, 1, 4]);
|
||||
|
||||
// I hit F3 to "Find Next" to find the next occurrence of ABC, but instead it searches for XYZ.
|
||||
nextMatchFindAction.run(null, editor);
|
||||
await nextMatchFindAction.run(null, editor);
|
||||
|
||||
assert.equal(findState.searchString, 'ABC');
|
||||
assert.equal(findController.hasFocus, false);
|
||||
@@ -210,10 +210,10 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #3090: F3 does not loop with two matches on a single line', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #3090: F3 does not loop with two matches on a single line', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'import nls = require(\'vs/nls\');'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
let nextMatchFindAction = new NextMatchFindAction();
|
||||
@@ -223,22 +223,22 @@ suite.skip('FindController', () => {
|
||||
column: 9
|
||||
});
|
||||
|
||||
nextMatchFindAction.run(null, editor);
|
||||
await nextMatchFindAction.run(null, editor);
|
||||
assert.deepEqual(fromSelection(editor.getSelection()!), [1, 26, 1, 29]);
|
||||
|
||||
nextMatchFindAction.run(null, editor);
|
||||
await nextMatchFindAction.run(null, editor);
|
||||
assert.deepEqual(fromSelection(editor.getSelection()!), [1, 8, 1, 11]);
|
||||
|
||||
findController.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #6149: Auto-escape highlighted text for search and replace regex mode', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #6149: Auto-escape highlighted text for search and replace regex mode', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
let startFindAction = new StartFindAction();
|
||||
@@ -247,22 +247,22 @@ suite.skip('FindController', () => {
|
||||
editor.setSelection(new Selection(1, 9, 1, 13));
|
||||
|
||||
findController.toggleRegex();
|
||||
startFindAction.run(null, editor);
|
||||
await startFindAction.run(null, editor);
|
||||
|
||||
nextMatchFindAction.run(null, editor);
|
||||
await nextMatchFindAction.run(null, editor);
|
||||
assert.deepEqual(fromSelection(editor.getSelection()!), [2, 9, 2, 13]);
|
||||
|
||||
nextMatchFindAction.run(null, editor);
|
||||
await nextMatchFindAction.run(null, editor);
|
||||
assert.deepEqual(fromSelection(editor.getSelection()!), [1, 9, 1, 13]);
|
||||
|
||||
findController.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #41027: Don\'t replace find input value on replace action if find input is active', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #41027: Don\'t replace find input value on replace action if find input is active', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'test',
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
let testRegexString = 'tes.';
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
let nextMatchFindAction = new NextMatchFindAction();
|
||||
@@ -270,7 +270,7 @@ suite.skip('FindController', () => {
|
||||
|
||||
findController.toggleRegex();
|
||||
findController.setSearchString(testRegexString);
|
||||
findController.start({
|
||||
await findController.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: false,
|
||||
seedSearchStringFromGlobalClipboard: false,
|
||||
@@ -279,8 +279,8 @@ suite.skip('FindController', () => {
|
||||
updateSearchScope: false,
|
||||
loop: true
|
||||
});
|
||||
nextMatchFindAction.run(null, editor);
|
||||
startFindReplaceAction.run(null, editor);
|
||||
await nextMatchFindAction.run(null, editor);
|
||||
await startFindReplaceAction.run(null, editor);
|
||||
|
||||
assert.equal(findController.getState().searchString, testRegexString);
|
||||
|
||||
@@ -288,15 +288,15 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #9043: Clear search scope when find widget is hidden', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #9043: Clear search scope when find widget is hidden', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
findController.start({
|
||||
await findController.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: false,
|
||||
seedSearchStringFromGlobalClipboard: false,
|
||||
@@ -319,15 +319,15 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #18111: Regex replace with single space replaces with no space', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #18111: Regex replace with single space replaces with no space', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'HRESULT OnAmbientPropertyChange(DISPID dispid);'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
|
||||
let startFindAction = new StartFindAction();
|
||||
startFindAction.run(null, editor);
|
||||
await startFindAction.run(null, editor);
|
||||
|
||||
findController.getState().change({ searchString: '\\b\\s{3}\\b', replaceString: ' ', isRegex: true }, false);
|
||||
findController.moveToNextMatch();
|
||||
@@ -344,17 +344,17 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #24714: Regular expression with ^ in search & replace', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #24714: Regular expression with ^ in search & replace', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'',
|
||||
'line2',
|
||||
'line3'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
|
||||
let startFindAction = new StartFindAction();
|
||||
startFindAction.run(null, editor);
|
||||
await startFindAction.run(null, editor);
|
||||
|
||||
findController.getState().change({ searchString: '^', replaceString: 'x', isRegex: true }, false);
|
||||
findController.moveToNextMatch();
|
||||
@@ -371,12 +371,12 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #38232: Find Next Selection, regex enabled', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #38232: Find Next Selection, regex enabled', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'([funny]',
|
||||
'',
|
||||
'([funny]'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
let nextSelectionMatchFindAction = new NextSelectionMatchFindAction();
|
||||
@@ -388,7 +388,7 @@ suite.skip('FindController', () => {
|
||||
editor.setSelection(new Selection(1, 1, 1, 9));
|
||||
|
||||
// cmd+f3
|
||||
nextSelectionMatchFindAction.run(null, editor);
|
||||
await nextSelectionMatchFindAction.run(null, editor);
|
||||
|
||||
assert.deepEqual(editor.getSelections()!.map(fromSelection), [
|
||||
[3, 1, 3, 9]
|
||||
@@ -398,19 +398,19 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #38232: Find Next Selection, regex enabled, find widget open', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #38232: Find Next Selection, regex enabled, find widget open', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'([funny]',
|
||||
'',
|
||||
'([funny]'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
clipboardState = '';
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
let startFindAction = new StartFindAction();
|
||||
let nextSelectionMatchFindAction = new NextSelectionMatchFindAction();
|
||||
|
||||
// cmd+f - open find widget
|
||||
startFindAction.run(null, editor);
|
||||
await startFindAction.run(null, editor);
|
||||
|
||||
// toggle regex
|
||||
findController.getState().change({ isRegex: true }, false);
|
||||
@@ -419,7 +419,7 @@ suite.skip('FindController', () => {
|
||||
editor.setSelection(new Selection(1, 1, 1, 9));
|
||||
|
||||
// cmd+f3
|
||||
nextSelectionMatchFindAction.run(null, editor);
|
||||
await nextSelectionMatchFindAction.run(null, editor);
|
||||
|
||||
assert.deepEqual(editor.getSelections()!.map(fromSelection), [
|
||||
[3, 1, 3, 9]
|
||||
@@ -430,7 +430,7 @@ suite.skip('FindController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
suite.skip('FindController query options persistence', () => {
|
||||
suite.skip('FindController query options persistence', async () => {
|
||||
let queryState: { [key: string]: any; } = {};
|
||||
queryState['editor.isRegex'] = false;
|
||||
queryState['editor.matchCase'] = false;
|
||||
@@ -447,13 +447,13 @@ suite.skip('FindController query options persistence', () => {
|
||||
remove: () => undefined
|
||||
} as any);
|
||||
|
||||
test('matchCase', () => {
|
||||
withTestCodeEditor([
|
||||
test('matchCase', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'abc',
|
||||
'ABC',
|
||||
'XYZ',
|
||||
'ABC'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
queryState = { 'editor.isRegex': false, 'editor.matchCase': true, 'editor.wholeWord': false };
|
||||
// The cursor is at the very top, of the file, at the first ABC
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
@@ -461,7 +461,7 @@ suite.skip('FindController query options persistence', () => {
|
||||
let startFindAction = new StartFindAction();
|
||||
|
||||
// I hit Ctrl+F to show the Find dialog
|
||||
startFindAction.run(null, editor);
|
||||
await startFindAction.run(null, editor);
|
||||
|
||||
// I type ABC.
|
||||
findState.change({ searchString: 'ABC' }, true);
|
||||
@@ -474,13 +474,13 @@ suite.skip('FindController query options persistence', () => {
|
||||
|
||||
queryState = { 'editor.isRegex': false, 'editor.matchCase': false, 'editor.wholeWord': true };
|
||||
|
||||
test('wholeWord', () => {
|
||||
withTestCodeEditor([
|
||||
test('wholeWord', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'ABC',
|
||||
'AB',
|
||||
'XYZ',
|
||||
'ABC'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
queryState = { 'editor.isRegex': false, 'editor.matchCase': false, 'editor.wholeWord': true };
|
||||
// The cursor is at the very top, of the file, at the first ABC
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
@@ -488,7 +488,7 @@ suite.skip('FindController query options persistence', () => {
|
||||
let startFindAction = new StartFindAction();
|
||||
|
||||
// I hit Ctrl+F to show the Find dialog
|
||||
startFindAction.run(null, editor);
|
||||
await startFindAction.run(null, editor);
|
||||
|
||||
// I type AB.
|
||||
findState.change({ searchString: 'AB' }, true);
|
||||
@@ -499,13 +499,13 @@ suite.skip('FindController query options persistence', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('toggling options is saved', () => {
|
||||
withTestCodeEditor([
|
||||
test('toggling options is saved', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'ABC',
|
||||
'AB',
|
||||
'XYZ',
|
||||
'ABC'
|
||||
], { serviceCollection: serviceCollection }, (editor) => {
|
||||
], { serviceCollection: serviceCollection }, async (editor) => {
|
||||
queryState = { 'editor.isRegex': false, 'editor.matchCase': false, 'editor.wholeWord': true };
|
||||
// The cursor is at the very top, of the file, at the first ABC
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
@@ -516,17 +516,17 @@ suite.skip('FindController query options persistence', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #27083: Update search scope once find widget becomes visible', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #27083: Update search scope once find widget becomes visible', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, (editor) => {
|
||||
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, async (editor) => {
|
||||
// clipboardState = '';
|
||||
editor.setSelection(new Range(1, 1, 2, 1));
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
|
||||
findController.start({
|
||||
await findController.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: false,
|
||||
seedSearchStringFromGlobalClipboard: false,
|
||||
@@ -540,17 +540,17 @@ suite.skip('FindController query options persistence', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #58604: Do not update searchScope if it is empty', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #58604: Do not update searchScope if it is empty', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, (editor) => {
|
||||
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, async (editor) => {
|
||||
// clipboardState = '';
|
||||
editor.setSelection(new Range(1, 2, 1, 2));
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
|
||||
findController.start({
|
||||
await findController.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: false,
|
||||
seedSearchStringFromGlobalClipboard: false,
|
||||
@@ -564,17 +564,17 @@ suite.skip('FindController query options persistence', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #58604: Update searchScope if it is not empty', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #58604: Update searchScope if it is not empty', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, (editor) => {
|
||||
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'always', globalFindClipboard: false } }, async (editor) => {
|
||||
// clipboardState = '';
|
||||
editor.setSelection(new Range(1, 2, 1, 3));
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
|
||||
findController.start({
|
||||
await findController.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: false,
|
||||
seedSearchStringFromGlobalClipboard: false,
|
||||
@@ -589,17 +589,17 @@ suite.skip('FindController query options persistence', () => {
|
||||
});
|
||||
|
||||
|
||||
test('issue #27083: Find in selection when multiple lines are selected', () => {
|
||||
withTestCodeEditor([
|
||||
test('issue #27083: Find in selection when multiple lines are selected', async () => {
|
||||
await withAsyncTestCodeEditor([
|
||||
'var x = (3 * 5)',
|
||||
'var y = (3 * 5)',
|
||||
'var z = (3 * 5)',
|
||||
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'multiline', globalFindClipboard: false } }, (editor) => {
|
||||
], { serviceCollection: serviceCollection, find: { autoFindInSelection: 'multiline', globalFindClipboard: false } }, async (editor) => {
|
||||
// clipboardState = '';
|
||||
editor.setSelection(new Range(1, 6, 2, 1));
|
||||
let findController = editor.registerAndInstantiateContribution(TestFindController.ID, TestFindController);
|
||||
|
||||
findController.start({
|
||||
await findController.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: false,
|
||||
seedSearchStringFromGlobalClipboard: false,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
.monaco-editor .monaco-editor-overlaymessage {
|
||||
padding-bottom: 8px;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
|
||||
@@ -29,8 +29,6 @@ export class MessageController extends Disposable implements IEditorContribution
|
||||
return editor.getContribution<MessageController>(MessageController.ID);
|
||||
}
|
||||
|
||||
private readonly closeTimeout = 3000; // close after 3s
|
||||
|
||||
private readonly _editor: ICodeEditor;
|
||||
private readonly _visible: IContextKey<boolean>;
|
||||
private readonly _messageWidget = this._register(new MutableDisposable<MessageWidget>());
|
||||
@@ -70,7 +68,8 @@ export class MessageController extends Disposable implements IEditorContribution
|
||||
this._messageListeners.add(this._editor.onDidDispose(() => this.closeMessage()));
|
||||
this._messageListeners.add(this._editor.onDidChangeModel(() => this.closeMessage()));
|
||||
|
||||
this._messageListeners.add(new TimeoutTimer(() => this.closeMessage(), this.closeTimeout));
|
||||
// 3sec
|
||||
this._messageListeners.add(new TimeoutTimer(() => this.closeMessage(), 3000));
|
||||
|
||||
// close on mouse move
|
||||
let bounds: Range;
|
||||
|
||||
@@ -169,7 +169,7 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
container.appendChild(this._bodyElement);
|
||||
}
|
||||
|
||||
protected _fillHead(container: HTMLElement): void {
|
||||
protected _fillHead(container: HTMLElement, noCloseAction?: boolean): void {
|
||||
const titleElement = dom.$('.peekview-title');
|
||||
dom.append(this._headElement!, titleElement);
|
||||
dom.addStandardDisposableListener(titleElement, 'click', event => this._onTitleClick(event));
|
||||
@@ -187,10 +187,12 @@ export abstract class PeekViewWidget extends ZoneWidget {
|
||||
this._actionbarWidget = new ActionBar(actionsContainer, actionBarOptions);
|
||||
this._disposables.add(this._actionbarWidget);
|
||||
|
||||
this._actionbarWidget.push(new Action('peekview.close', nls.localize('label.close', "Close"), Codicon.close.classNames, true, () => {
|
||||
this.dispose();
|
||||
return Promise.resolve();
|
||||
}), { label: false, icon: true });
|
||||
if (!noCloseAction) {
|
||||
this._actionbarWidget.push(new Action('peekview.close', nls.localize('label.close', "Close"), Codicon.close.classNames, true, () => {
|
||||
this.dispose();
|
||||
return Promise.resolve();
|
||||
}), { label: false, icon: true });
|
||||
}
|
||||
}
|
||||
|
||||
protected _fillTitleIcon(container: HTMLElement): void {
|
||||
|
||||
@@ -174,9 +174,9 @@ export class OneSnippet {
|
||||
}
|
||||
|
||||
return selections;
|
||||
})!;
|
||||
});
|
||||
|
||||
return !couldSkipThisPlaceholder ? newSelections : this.move(fwd);
|
||||
return !couldSkipThisPlaceholder ? newSelections ?? [] : this.move(fwd);
|
||||
}
|
||||
|
||||
private _hasPlaceholderBeenCollapsed(placeholder: Placeholder): boolean {
|
||||
@@ -450,7 +450,7 @@ export class SnippetSession {
|
||||
modelBasedVariableResolver,
|
||||
new ClipboardBasedVariableResolver(readClipboardText, idx, indexedSelections.length, editor.getOption(EditorOption.multiCursorPaste) === 'spread'),
|
||||
new SelectionBasedVariableResolver(model, selection),
|
||||
new CommentBasedVariableResolver(model),
|
||||
new CommentBasedVariableResolver(model, selection),
|
||||
new TimeBasedVariableResolver,
|
||||
new WorkspaceBasedVariableResolver(workspaceService),
|
||||
new RandomBasedVariableResolver,
|
||||
@@ -503,11 +503,9 @@ export class SnippetSession {
|
||||
if (this._snippets[0].hasPlaceholder) {
|
||||
return this._move(true);
|
||||
} else {
|
||||
return (
|
||||
undoEdits
|
||||
.filter(edit => !!edit.identifier) // only use our undo edits
|
||||
.map(edit => Selection.fromPositions(edit.range.getEndPosition()))
|
||||
);
|
||||
return undoEdits
|
||||
.filter(edit => !!edit.identifier) // only use our undo edits
|
||||
.map(edit => Selection.fromPositions(edit.range.getEndPosition()));
|
||||
}
|
||||
});
|
||||
this._editor.revealRange(this._editor.getSelections()[0]);
|
||||
|
||||
@@ -208,14 +208,15 @@ export class ClipboardBasedVariableResolver implements VariableResolver {
|
||||
}
|
||||
export class CommentBasedVariableResolver implements VariableResolver {
|
||||
constructor(
|
||||
private readonly _model: ITextModel
|
||||
private readonly _model: ITextModel,
|
||||
private readonly _selection: Selection
|
||||
) {
|
||||
//
|
||||
}
|
||||
resolve(variable: Variable): string | undefined {
|
||||
const { name } = variable;
|
||||
const language = this._model.getLanguageIdentifier();
|
||||
const config = LanguageConfigurationRegistry.getComments(language.id);
|
||||
const langId = this._model.getLanguageIdAtPosition(this._selection.selectionStartLineNumber, this._selection.selectionStartColumn);
|
||||
const config = LanguageConfigurationRegistry.getComments(langId);
|
||||
if (!config) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -439,4 +439,13 @@ suite('SnippetController2', function () {
|
||||
ctrl.insert('\nfoo');
|
||||
assertSelections(editor, new Selection(2, 8, 2, 8));
|
||||
});
|
||||
|
||||
test('leading TAB by snippets won\'t replace by spaces #101870', function () {
|
||||
this.skip();
|
||||
const ctrl = new SnippetController2(editor, logService, contextKeys);
|
||||
model.setValue('');
|
||||
model.updateOptions({ insertSpaces: true, tabSize: 4 });
|
||||
ctrl.insert('\tHello World\n\tNew Line');
|
||||
assert.strictEqual(model.getValue(), ' Hello World\n New Line');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -447,7 +447,7 @@ export class SuggestModel implements IDisposable {
|
||||
}
|
||||
|
||||
let clipboardText: string | undefined;
|
||||
if (completions.needsClipboard) {
|
||||
if (completions.needsClipboard || isNonEmptyArray(existingItems)) {
|
||||
clipboardText = await this._clipboardService.readText();
|
||||
}
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@ class SuggestionDetails {
|
||||
|
||||
// --- details
|
||||
if (detail) {
|
||||
this.type.innerText = detail;
|
||||
this.type.innerText = detail.length > 100_000 ? `${detail.substr(0, 100_000)}…` : detail;
|
||||
show(this.type);
|
||||
} else {
|
||||
this.type.innerText = '';
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { Disposable, IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditor, IDiffEditor, IEditorConstructionOptions } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
|
||||
import { IDiffEditorOptions, IEditorOptions, IEditorConstructionOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { InternalEditorAction } from 'vs/editor/common/editorAction';
|
||||
import { IModelChangedEvent } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ICodeEditor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditor, IActiveCodeEditor, IEditorConstructionOptions } from 'vs/editor/browser/editorBrowser';
|
||||
import { IEditorContributionCtor } from 'vs/editor/browser/editorExtensions';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { View } from 'vs/editor/browser/view/viewImpl';
|
||||
@@ -34,7 +34,7 @@ export interface ITestCodeEditor extends IActiveCodeEditor {
|
||||
class TestCodeEditor extends CodeEditorWidget implements ICodeEditor {
|
||||
|
||||
//#region testing overrides
|
||||
protected _createConfiguration(options: editorOptions.IEditorConstructionOptions): IConfiguration {
|
||||
protected _createConfiguration(options: IEditorConstructionOptions): IConfiguration {
|
||||
return new TestConfiguration(options);
|
||||
}
|
||||
protected _createView(viewModel: ViewModel): [View, boolean] {
|
||||
@@ -96,6 +96,24 @@ export function withTestCodeEditor(text: string | string[] | null, options: Test
|
||||
editor.dispose();
|
||||
}
|
||||
|
||||
export async function withAsyncTestCodeEditor(text: string | string[] | null, options: TestCodeEditorCreationOptions, callback: (editor: ITestCodeEditor, viewModel: ViewModel) => Promise<void>): Promise<void> {
|
||||
// create a model if necessary and remember it in order to dispose it.
|
||||
if (!options.model) {
|
||||
if (typeof text === 'string') {
|
||||
options.model = createTextModel(text);
|
||||
} else if (text) {
|
||||
options.model = createTextModel(text.join('\n'));
|
||||
}
|
||||
}
|
||||
|
||||
const editor = createTestCodeEditor(options);
|
||||
const viewModel = editor.getViewModel()!;
|
||||
viewModel.setHasFocus(true);
|
||||
await callback(<ITestCodeEditor>editor, editor.getViewModel()!);
|
||||
|
||||
editor.dispose();
|
||||
}
|
||||
|
||||
export function createTestCodeEditor(options: TestCodeEditorCreationOptions): ITestCodeEditor {
|
||||
|
||||
const model = options.model;
|
||||
|
||||
+31
-7
@@ -195,7 +195,7 @@ var AMDLoader;
|
||||
return isEmpty;
|
||||
};
|
||||
Utilities.recursiveClone = function (obj) {
|
||||
if (!obj || typeof obj !== 'object') {
|
||||
if (!obj || typeof obj !== 'object' || obj instanceof RegExp) {
|
||||
return obj;
|
||||
}
|
||||
var result = Array.isArray(obj) ? [] : {};
|
||||
@@ -304,6 +304,9 @@ var AMDLoader;
|
||||
if (typeof options.cspNonce !== 'string') {
|
||||
options.cspNonce = '';
|
||||
}
|
||||
if (typeof options.preferScriptTags === 'undefined') {
|
||||
options.preferScriptTags = false;
|
||||
}
|
||||
if (!Array.isArray(options.nodeModules)) {
|
||||
options.nodeModules = [];
|
||||
}
|
||||
@@ -459,7 +462,9 @@ var AMDLoader;
|
||||
* Transform a module id to a location. Appends .js to module ids
|
||||
*/
|
||||
Configuration.prototype.moduleIdToPaths = function (moduleId) {
|
||||
if (this.nodeModulesMap[moduleId] === true) {
|
||||
var isNodeModule = ((this.nodeModulesMap[moduleId] === true)
|
||||
|| (this.options.amdModulesPattern instanceof RegExp && !this.options.amdModulesPattern.test(moduleId)));
|
||||
if (isNodeModule) {
|
||||
// This is a node module...
|
||||
if (this.isBuild()) {
|
||||
// ...and we are at build time, drop it
|
||||
@@ -567,11 +572,24 @@ var AMDLoader;
|
||||
OnlyOnceScriptLoader.prototype.load = function (moduleManager, scriptSrc, callback, errorback) {
|
||||
var _this = this;
|
||||
if (!this._scriptLoader) {
|
||||
this._scriptLoader = (this._env.isWebWorker
|
||||
? new WorkerScriptLoader()
|
||||
: this._env.isNode
|
||||
? new NodeScriptLoader(this._env)
|
||||
: new BrowserScriptLoader());
|
||||
if (this._env.isWebWorker) {
|
||||
this._scriptLoader = new WorkerScriptLoader();
|
||||
}
|
||||
else if (this._env.isElectronRenderer) {
|
||||
var preferScriptTags = moduleManager.getConfig().getOptionsLiteral().preferScriptTags;
|
||||
if (preferScriptTags) {
|
||||
this._scriptLoader = new BrowserScriptLoader();
|
||||
}
|
||||
else {
|
||||
this._scriptLoader = new NodeScriptLoader(this._env);
|
||||
}
|
||||
}
|
||||
else if (this._env.isNode) {
|
||||
this._scriptLoader = new NodeScriptLoader(this._env);
|
||||
}
|
||||
else {
|
||||
this._scriptLoader = new BrowserScriptLoader();
|
||||
}
|
||||
}
|
||||
var scriptCallbacks = {
|
||||
callback: callback,
|
||||
@@ -870,6 +888,12 @@ var AMDLoader;
|
||||
}
|
||||
var cachedData = script.createCachedData();
|
||||
if (cachedData.length === 0 || cachedData.length === lastSize || iteration >= 5) {
|
||||
// done
|
||||
return;
|
||||
}
|
||||
if (cachedData.length < lastSize) {
|
||||
// less data than before: skip, try again next round
|
||||
createLoop();
|
||||
return;
|
||||
}
|
||||
lastSize = cachedData.length;
|
||||
|
||||
Vendored
+28
-8
@@ -3138,13 +3138,6 @@ declare namespace monaco.editor {
|
||||
showDeprecated?: boolean;
|
||||
}
|
||||
|
||||
export interface IEditorConstructionOptions extends IEditorOptions {
|
||||
/**
|
||||
* The initial editor dimension (to avoid measuring the container).
|
||||
*/
|
||||
dimension?: IDimension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration options for the diff editor.
|
||||
*/
|
||||
@@ -3179,10 +3172,20 @@ declare namespace monaco.editor {
|
||||
* Defaults to false.
|
||||
*/
|
||||
originalEditable?: boolean;
|
||||
/**
|
||||
/** // {{SQL CARBON EDIT}}
|
||||
* Adding option to reverse coloring in diff editor
|
||||
*/
|
||||
reverse?: boolean;
|
||||
/**
|
||||
* Original editor should be have code lens enabled?
|
||||
* Defaults to false.
|
||||
*/
|
||||
originalCodeLens?: boolean;
|
||||
/**
|
||||
* Modified editor should be have code lens enabled?
|
||||
* Defaults to false.
|
||||
*/
|
||||
modifiedCodeLens?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3214,6 +3217,11 @@ declare namespace monaco.editor {
|
||||
* Defaults to true.
|
||||
*/
|
||||
insertSpace?: boolean;
|
||||
/**
|
||||
* Ignore empty lines when inserting line comments.
|
||||
* Defaults to true.
|
||||
*/
|
||||
ignoreEmptyLines?: boolean;
|
||||
}
|
||||
|
||||
export type EditorCommentsOptions = Readonly<Required<IEditorCommentsOptions>>;
|
||||
@@ -4394,6 +4402,18 @@ declare namespace monaco.editor {
|
||||
readonly mode: string | null;
|
||||
}
|
||||
|
||||
export interface IEditorConstructionOptions extends IEditorOptions {
|
||||
/**
|
||||
* The initial editor dimension (to avoid measuring the container).
|
||||
*/
|
||||
dimension?: IDimension;
|
||||
/**
|
||||
* Place overflow widgets inside an external DOM node.
|
||||
* Defaults to an internal DOM node.
|
||||
*/
|
||||
overflowWidgetsDomNode?: HTMLElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* A rich code editor.
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as json from 'vs/base/common/json';
|
||||
import { ResourceMap, values, getOrSet } from 'vs/base/common/map';
|
||||
import { ResourceMap, getOrSet } from 'vs/base/common/map';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
@@ -692,7 +692,7 @@ export class Configuration {
|
||||
this.userConfiguration.freeze().keys.forEach(key => keys.add(key));
|
||||
this._workspaceConfiguration.freeze().keys.forEach(key => keys.add(key));
|
||||
this._folderConfigurations.forEach(folderConfiguraiton => folderConfiguraiton.freeze().keys.forEach(key => keys.add(key)));
|
||||
return values(keys);
|
||||
return [...keys.values()];
|
||||
}
|
||||
|
||||
protected getAllKeysForOverrideIdentifier(overrideIdentifier: string): string[] {
|
||||
@@ -701,7 +701,7 @@ export class Configuration {
|
||||
this.userConfiguration.getKeysForOverrideIdentifier(overrideIdentifier).forEach(key => keys.add(key));
|
||||
this._workspaceConfiguration.getKeysForOverrideIdentifier(overrideIdentifier).forEach(key => keys.add(key));
|
||||
this._folderConfigurations.forEach(folderConfiguraiton => folderConfiguraiton.getKeysForOverrideIdentifier(overrideIdentifier).forEach(key => keys.add(key)));
|
||||
return values(keys);
|
||||
return [...keys.values()];
|
||||
}
|
||||
|
||||
static parse(data: IConfigurationData): Configuration {
|
||||
@@ -738,8 +738,8 @@ export function mergeChanges(...changes: IConfigurationChange[]): IConfiguration
|
||||
});
|
||||
}
|
||||
const overrides: [string, string[]][] = [];
|
||||
overridesMap.forEach((keys, identifier) => overrides.push([identifier, values(keys)]));
|
||||
return { keys: values(keysSet), overrides };
|
||||
overridesMap.forEach((keys, identifier) => overrides.push([identifier, [...keys.values()]]));
|
||||
return { keys: [...keysSet.values()], overrides };
|
||||
}
|
||||
|
||||
export class ConfigurationChangeEvent implements IConfigurationChangeEvent {
|
||||
@@ -753,7 +753,7 @@ export class ConfigurationChangeEvent implements IConfigurationChangeEvent {
|
||||
const keysSet = new Set<string>();
|
||||
change.keys.forEach(key => keysSet.add(key));
|
||||
change.overrides.forEach(([, keys]) => keys.forEach(key => keysSet.add(key)));
|
||||
this.affectedKeys = values(keysSet);
|
||||
this.affectedKeys = [...keysSet.values()];
|
||||
|
||||
const configurationModel = new ConfigurationModel();
|
||||
this.affectedKeys.forEach(key => configurationModel.setValue(key, {}));
|
||||
|
||||
@@ -10,7 +10,6 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { values } from 'vs/base/common/map';
|
||||
|
||||
export const Extensions = {
|
||||
Configuration: 'base.contributions.configuration'
|
||||
@@ -395,7 +394,7 @@ class ConfigurationRegistry implements IConfigurationRegistry {
|
||||
}
|
||||
|
||||
private updateOverridePropertyPatternKey(): void {
|
||||
for (const overrideIdentifier of values(this.overrideIdentifiers)) {
|
||||
for (const overrideIdentifier of this.overrideIdentifiers.values()) {
|
||||
const overrideIdentifierProperty = `[${overrideIdentifier}]`;
|
||||
const resourceLanguagePropertiesSchema: IJSONSchema = {
|
||||
type: 'object',
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
|
||||
|
||||
suite('ConfigurationService', () => {
|
||||
|
||||
let fileService: IFileService;
|
||||
let settingsResource: URI;
|
||||
const disposables: DisposableStore = new DisposableStore();
|
||||
|
||||
setup(async () => {
|
||||
fileService = disposables.add(new FileService(new NullLogService()));
|
||||
const diskFileSystemProvider = disposables.add(new InMemoryFileSystemProvider());
|
||||
fileService.registerProvider(Schemas.file, diskFileSystemProvider);
|
||||
settingsResource = URI.file('settings.json');
|
||||
});
|
||||
|
||||
teardown(() => disposables.clear());
|
||||
|
||||
test('simple', async () => {
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }'));
|
||||
const testObject = disposables.add(new ConfigurationService(settingsResource, fileService));
|
||||
await testObject.initialize();
|
||||
const config = testObject.getValue<{
|
||||
foo: string;
|
||||
}>();
|
||||
|
||||
assert.ok(config);
|
||||
assert.equal(config.foo, 'bar');
|
||||
});
|
||||
|
||||
test('config gets flattened', async () => {
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "testworkbench.editor.tabs": true }'));
|
||||
|
||||
const testObject = disposables.add(new ConfigurationService(settingsResource, fileService));
|
||||
await testObject.initialize();
|
||||
const config = testObject.getValue<{
|
||||
testworkbench: {
|
||||
editor: {
|
||||
tabs: boolean;
|
||||
};
|
||||
};
|
||||
}>();
|
||||
|
||||
assert.ok(config);
|
||||
assert.ok(config.testworkbench);
|
||||
assert.ok(config.testworkbench.editor);
|
||||
assert.equal(config.testworkbench.editor.tabs, true);
|
||||
});
|
||||
|
||||
test('error case does not explode', async () => {
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString(',,,,'));
|
||||
|
||||
const testObject = disposables.add(new ConfigurationService(settingsResource, fileService));
|
||||
await testObject.initialize();
|
||||
const config = testObject.getValue<{
|
||||
foo: string;
|
||||
}>();
|
||||
|
||||
assert.ok(config);
|
||||
});
|
||||
|
||||
test('missing file does not explode', async () => {
|
||||
const testObject = disposables.add(new ConfigurationService(URI.file('__testFile'), fileService));
|
||||
await testObject.initialize();
|
||||
|
||||
const config = testObject.getValue<{ foo: string }>();
|
||||
|
||||
assert.ok(config);
|
||||
});
|
||||
|
||||
test('trigger configuration change event when file does not exist', async () => {
|
||||
const testObject = disposables.add(new ConfigurationService(settingsResource, fileService));
|
||||
await testObject.initialize();
|
||||
return new Promise(async (c, e) => {
|
||||
disposables.add(Event.filter(testObject.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(() => {
|
||||
assert.equal(testObject.getValue('foo'), 'bar');
|
||||
c();
|
||||
}));
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('trigger configuration change event when file exists', async () => {
|
||||
const testObject = disposables.add(new ConfigurationService(settingsResource, fileService));
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }'));
|
||||
await testObject.initialize();
|
||||
|
||||
return new Promise((c, e) => {
|
||||
disposables.add(Event.filter(testObject.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => {
|
||||
assert.equal(testObject.getValue('foo'), 'barz');
|
||||
c();
|
||||
}));
|
||||
fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "barz" }'));
|
||||
});
|
||||
});
|
||||
|
||||
test('reloadConfiguration', async () => {
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }'));
|
||||
|
||||
const testObject = disposables.add(new ConfigurationService(settingsResource, fileService));
|
||||
await testObject.initialize();
|
||||
let config = testObject.getValue<{
|
||||
foo: string;
|
||||
}>();
|
||||
assert.ok(config);
|
||||
assert.equal(config.foo, 'bar');
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "changed" }'));
|
||||
|
||||
// force a reload to get latest
|
||||
await testObject.reloadConfiguration();
|
||||
config = testObject.getValue<{
|
||||
foo: string;
|
||||
}>();
|
||||
assert.ok(config);
|
||||
assert.equal(config.foo, 'changed');
|
||||
});
|
||||
|
||||
test('model defaults', async () => {
|
||||
interface ITestSetting {
|
||||
configuration: {
|
||||
service: {
|
||||
testSetting: string;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': '_test',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'configuration.service.testSetting': {
|
||||
'type': 'string',
|
||||
'default': 'isSet'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let testObject = disposables.add(new ConfigurationService(URI.file('__testFile'), fileService));
|
||||
await testObject.initialize();
|
||||
let setting = testObject.getValue<ITestSetting>();
|
||||
|
||||
assert.ok(setting);
|
||||
assert.equal(setting.configuration.service.testSetting, 'isSet');
|
||||
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "testworkbench.editor.tabs": true }'));
|
||||
testObject = disposables.add(new ConfigurationService(settingsResource, fileService));
|
||||
|
||||
setting = testObject.getValue<ITestSetting>();
|
||||
|
||||
assert.ok(setting);
|
||||
assert.equal(setting.configuration.service.testSetting, 'isSet');
|
||||
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "configuration.service.testSetting": "isChanged" }'));
|
||||
|
||||
await testObject.reloadConfiguration();
|
||||
setting = testObject.getValue<ITestSetting>();
|
||||
assert.ok(setting);
|
||||
assert.equal(setting.configuration.service.testSetting, 'isChanged');
|
||||
});
|
||||
|
||||
test('lookup', async () => {
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': '_test',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'lookup.service.testSetting': {
|
||||
'type': 'string',
|
||||
'default': 'isSet'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const testObject = disposables.add(new ConfigurationService(settingsResource, fileService));
|
||||
testObject.initialize();
|
||||
|
||||
let res = testObject.inspect('something.missing');
|
||||
assert.strictEqual(res.value, undefined);
|
||||
assert.strictEqual(res.defaultValue, undefined);
|
||||
assert.strictEqual(res.userValue, undefined);
|
||||
|
||||
res = testObject.inspect('lookup.service.testSetting');
|
||||
assert.strictEqual(res.defaultValue, 'isSet');
|
||||
assert.strictEqual(res.value, 'isSet');
|
||||
assert.strictEqual(res.userValue, undefined);
|
||||
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "lookup.service.testSetting": "bar" }'));
|
||||
|
||||
await testObject.reloadConfiguration();
|
||||
res = testObject.inspect('lookup.service.testSetting');
|
||||
assert.strictEqual(res.defaultValue, 'isSet');
|
||||
assert.strictEqual(res.userValue, 'bar');
|
||||
assert.strictEqual(res.value, 'bar');
|
||||
|
||||
});
|
||||
|
||||
test('lookup with null', async () => {
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': '_testNull',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'lookup.service.testNullSetting': {
|
||||
'type': 'null',
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const testObject = disposables.add(new ConfigurationService(settingsResource, fileService));
|
||||
testObject.initialize();
|
||||
|
||||
let res = testObject.inspect('lookup.service.testNullSetting');
|
||||
assert.strictEqual(res.defaultValue, null);
|
||||
assert.strictEqual(res.value, null);
|
||||
assert.strictEqual(res.userValue, undefined);
|
||||
|
||||
await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "lookup.service.testNullSetting": null }'));
|
||||
|
||||
await testObject.reloadConfiguration();
|
||||
|
||||
res = testObject.inspect('lookup.service.testNullSetting');
|
||||
assert.strictEqual(res.defaultValue, null);
|
||||
assert.strictEqual(res.value, null);
|
||||
assert.strictEqual(res.userValue, null);
|
||||
});
|
||||
});
|
||||
@@ -1,304 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as os from 'os';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||
import * as uuid from 'vs/base/common/uuid';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { testFile } from 'vs/base/test/node/utils';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { FileService } from 'vs/platform/files/common/fileService';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
|
||||
suite('ConfigurationService - Node', () => {
|
||||
|
||||
let fileService: IFileService;
|
||||
const disposables: IDisposable[] = [];
|
||||
|
||||
setup(() => {
|
||||
const logService = new NullLogService();
|
||||
fileService = new FileService(logService);
|
||||
disposables.push(fileService);
|
||||
const diskFileSystemProvider = new DiskFileSystemProvider(logService);
|
||||
disposables.push(diskFileSystemProvider);
|
||||
fileService.registerProvider(Schemas.file, diskFileSystemProvider);
|
||||
});
|
||||
|
||||
test('simple', async () => {
|
||||
const res = await testFile('config', 'config.json');
|
||||
fs.writeFileSync(res.testFile, '{ "foo": "bar" }');
|
||||
|
||||
const service = new ConfigurationService(URI.file(res.testFile), fileService);
|
||||
await service.initialize();
|
||||
const config = service.getValue<{
|
||||
foo: string;
|
||||
}>();
|
||||
|
||||
assert.ok(config);
|
||||
assert.equal(config.foo, 'bar');
|
||||
service.dispose();
|
||||
|
||||
return res.cleanUp();
|
||||
});
|
||||
|
||||
test('config gets flattened', async () => {
|
||||
const res = await testFile('config', 'config.json');
|
||||
|
||||
fs.writeFileSync(res.testFile, '{ "testworkbench.editor.tabs": true }');
|
||||
|
||||
const service = new ConfigurationService(URI.file(res.testFile), fileService);
|
||||
await service.initialize();
|
||||
const config = service.getValue<{
|
||||
testworkbench: {
|
||||
editor: {
|
||||
tabs: boolean;
|
||||
};
|
||||
};
|
||||
}>();
|
||||
assert.ok(config);
|
||||
assert.ok(config.testworkbench);
|
||||
assert.ok(config.testworkbench.editor);
|
||||
assert.equal(config.testworkbench.editor.tabs, true);
|
||||
|
||||
service.dispose();
|
||||
return res.cleanUp();
|
||||
});
|
||||
|
||||
test('error case does not explode', async () => {
|
||||
const res = await testFile('config', 'config.json');
|
||||
|
||||
fs.writeFileSync(res.testFile, ',,,,');
|
||||
|
||||
const service = new ConfigurationService(URI.file(res.testFile), fileService);
|
||||
await service.initialize();
|
||||
const config = service.getValue<{
|
||||
foo: string;
|
||||
}>();
|
||||
assert.ok(config);
|
||||
|
||||
service.dispose();
|
||||
return res.cleanUp();
|
||||
});
|
||||
|
||||
test('missing file does not explode', async () => {
|
||||
const id = uuid.generateUuid();
|
||||
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
|
||||
const newDir = path.join(parentDir, 'config', id);
|
||||
const testFile = path.join(newDir, 'config.json');
|
||||
|
||||
const service = new ConfigurationService(URI.file(testFile), fileService);
|
||||
await service.initialize();
|
||||
|
||||
const config = service.getValue<{ foo: string }>();
|
||||
assert.ok(config);
|
||||
|
||||
service.dispose();
|
||||
});
|
||||
|
||||
test('trigger configuration change event when file does not exist', async () => {
|
||||
const res = await testFile('config', 'config.json');
|
||||
const settingsFile = URI.file(res.testFile);
|
||||
const service = new ConfigurationService(settingsFile, fileService);
|
||||
await service.initialize();
|
||||
return new Promise(async (c, e) => {
|
||||
const disposable = Event.filter(service.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => {
|
||||
disposable.dispose();
|
||||
assert.equal(service.getValue('foo'), 'bar');
|
||||
service.dispose();
|
||||
await res.cleanUp();
|
||||
c();
|
||||
});
|
||||
await fileService.writeFile(settingsFile, VSBuffer.fromString('{ "foo": "bar" }'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('trigger configuration change event when file exists', async () => {
|
||||
const res = await testFile('config', 'config.json');
|
||||
|
||||
const service = new ConfigurationService(URI.file(res.testFile), fileService);
|
||||
fs.writeFileSync(res.testFile, '{ "foo": "bar" }');
|
||||
await service.initialize();
|
||||
return new Promise((c, e) => {
|
||||
const disposable = Event.filter(service.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => {
|
||||
disposable.dispose();
|
||||
assert.equal(service.getValue('foo'), 'barz');
|
||||
service.dispose();
|
||||
await res.cleanUp();
|
||||
c();
|
||||
});
|
||||
fs.writeFileSync(res.testFile, '{ "foo": "barz" }');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('reloadConfiguration', async () => {
|
||||
const res = await testFile('config', 'config.json');
|
||||
|
||||
fs.writeFileSync(res.testFile, '{ "foo": "bar" }');
|
||||
|
||||
const service = new ConfigurationService(URI.file(res.testFile), fileService);
|
||||
await service.initialize();
|
||||
let config = service.getValue<{
|
||||
foo: string;
|
||||
}>();
|
||||
assert.ok(config);
|
||||
assert.equal(config.foo, 'bar');
|
||||
fs.writeFileSync(res.testFile, '{ "foo": "changed" }');
|
||||
|
||||
// still outdated
|
||||
config = service.getValue<{
|
||||
foo: string;
|
||||
}>();
|
||||
assert.ok(config);
|
||||
assert.equal(config.foo, 'bar');
|
||||
|
||||
// force a reload to get latest
|
||||
await service.reloadConfiguration();
|
||||
config = service.getValue<{
|
||||
foo: string;
|
||||
}>();
|
||||
assert.ok(config);
|
||||
assert.equal(config.foo, 'changed');
|
||||
|
||||
service.dispose();
|
||||
return res.cleanUp();
|
||||
});
|
||||
|
||||
test('model defaults', async () => {
|
||||
interface ITestSetting {
|
||||
configuration: {
|
||||
service: {
|
||||
testSetting: string;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': '_test',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'configuration.service.testSetting': {
|
||||
'type': 'string',
|
||||
'default': 'isSet'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let serviceWithoutFile = new ConfigurationService(URI.file('__testFile'), fileService);
|
||||
await serviceWithoutFile.initialize();
|
||||
let setting = serviceWithoutFile.getValue<ITestSetting>();
|
||||
|
||||
assert.ok(setting);
|
||||
assert.equal(setting.configuration.service.testSetting, 'isSet');
|
||||
|
||||
return testFile('config', 'config.json').then(async res => {
|
||||
fs.writeFileSync(res.testFile, '{ "testworkbench.editor.tabs": true }');
|
||||
|
||||
const service = new ConfigurationService(URI.file(res.testFile), fileService);
|
||||
|
||||
let setting = service.getValue<ITestSetting>();
|
||||
|
||||
assert.ok(setting);
|
||||
assert.equal(setting.configuration.service.testSetting, 'isSet');
|
||||
|
||||
fs.writeFileSync(res.testFile, '{ "configuration.service.testSetting": "isChanged" }');
|
||||
|
||||
await service.reloadConfiguration();
|
||||
let setting_1 = service.getValue<ITestSetting>();
|
||||
assert.ok(setting_1);
|
||||
assert.equal(setting_1.configuration.service.testSetting, 'isChanged');
|
||||
service.dispose();
|
||||
serviceWithoutFile.dispose();
|
||||
return res.cleanUp();
|
||||
});
|
||||
});
|
||||
|
||||
test('lookup', async () => {
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': '_test',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'lookup.service.testSetting': {
|
||||
'type': 'string',
|
||||
'default': 'isSet'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const r = await testFile('config', 'config.json');
|
||||
const service = new ConfigurationService(URI.file(r.testFile), fileService);
|
||||
service.initialize();
|
||||
|
||||
let res = service.inspect('something.missing');
|
||||
assert.strictEqual(res.value, undefined);
|
||||
assert.strictEqual(res.defaultValue, undefined);
|
||||
assert.strictEqual(res.userValue, undefined);
|
||||
|
||||
res = service.inspect('lookup.service.testSetting');
|
||||
assert.strictEqual(res.defaultValue, 'isSet');
|
||||
assert.strictEqual(res.value, 'isSet');
|
||||
assert.strictEqual(res.userValue, undefined);
|
||||
|
||||
fs.writeFileSync(r.testFile, '{ "lookup.service.testSetting": "bar" }');
|
||||
|
||||
await service.reloadConfiguration();
|
||||
res = service.inspect('lookup.service.testSetting');
|
||||
assert.strictEqual(res.defaultValue, 'isSet');
|
||||
assert.strictEqual(res.userValue, 'bar');
|
||||
assert.strictEqual(res.value, 'bar');
|
||||
|
||||
service.dispose();
|
||||
return r.cleanUp();
|
||||
});
|
||||
|
||||
test('lookup with null', async () => {
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
configurationRegistry.registerConfiguration({
|
||||
'id': '_testNull',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'lookup.service.testNullSetting': {
|
||||
'type': 'null',
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const r = await testFile('config', 'config.json');
|
||||
const service = new ConfigurationService(URI.file(r.testFile), fileService);
|
||||
service.initialize();
|
||||
|
||||
let res = service.inspect('lookup.service.testNullSetting');
|
||||
assert.strictEqual(res.defaultValue, null);
|
||||
assert.strictEqual(res.value, null);
|
||||
assert.strictEqual(res.userValue, undefined);
|
||||
|
||||
fs.writeFileSync(r.testFile, '{ "lookup.service.testNullSetting": null }');
|
||||
|
||||
await service.reloadConfiguration();
|
||||
|
||||
res = service.inspect('lookup.service.testNullSetting');
|
||||
assert.strictEqual(res.defaultValue, null);
|
||||
assert.strictEqual(res.value, null);
|
||||
assert.strictEqual(res.userValue, null);
|
||||
|
||||
service.dispose();
|
||||
return r.cleanUp();
|
||||
});
|
||||
});
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
import { Emitter, Event, PauseableEmitter } from 'vs/base/common/event';
|
||||
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContext, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget, IReadableSet, SET_CONTEXT_COMMAND_ID, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { toArray } from 'vs/base/common/arrays';
|
||||
|
||||
const KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context';
|
||||
|
||||
@@ -102,7 +102,7 @@ class ConfigAwareContextValuesContainer extends Context {
|
||||
this._listener = this._configurationService.onDidChangeConfiguration(event => {
|
||||
if (event.source === ConfigurationTarget.DEFAULT) {
|
||||
// new setting, reset everything
|
||||
const allKeys = keys(this._values);
|
||||
const allKeys = toArray(this._values.keys());
|
||||
this._values.clear();
|
||||
emitter.fire(new ArrayContextKeyChangeEvent(allKeys));
|
||||
} else {
|
||||
|
||||
@@ -1167,7 +1167,6 @@ export interface IContextKeyService {
|
||||
onDidChangeContext: Event<IContextKeyChangeEvent>;
|
||||
bufferChangeEvents(callback: Function): void;
|
||||
|
||||
|
||||
createKey<T>(key: string, defaultValue: T | undefined): IContextKey<T>;
|
||||
contextMatchesRules(rules: ContextKeyExpression | undefined): boolean;
|
||||
getContextKeyValue<T>(key: string): T | undefined;
|
||||
|
||||
@@ -63,6 +63,7 @@ export interface ICommonElectronService {
|
||||
openExternal(url: string): Promise<boolean>;
|
||||
updateTouchBar(items: ISerializableCommandAction[][]): Promise<void>;
|
||||
moveItemToTrash(fullPath: string, deleteOnFail?: boolean): Promise<boolean>;
|
||||
isAdmin(): Promise<boolean>;
|
||||
|
||||
// clipboard
|
||||
readClipboardText(type?: 'selection' | 'clipboard'): Promise<string>;
|
||||
|
||||
@@ -10,7 +10,7 @@ import { OpenContext } from 'vs/platform/windows/node/window';
|
||||
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { IOpenedWindow, IOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
|
||||
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { isMacintosh, isWindows, isRootUser } from 'vs/base/common/platform';
|
||||
import { ICommonElectronService } from 'vs/platform/electron/common/electron';
|
||||
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
@@ -302,6 +302,17 @@ export class ElectronMainService implements IElectronMainService {
|
||||
return shell.moveItemToTrash(fullPath);
|
||||
}
|
||||
|
||||
async isAdmin(): Promise<boolean> {
|
||||
let isAdmin: boolean;
|
||||
if (isWindows) {
|
||||
isAdmin = (await import('native-is-elevated'))();
|
||||
} else {
|
||||
isAdmin = isRootUser();
|
||||
}
|
||||
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@ export interface IEnvironmentService {
|
||||
backupHome: URI;
|
||||
untitledWorkspacesHome: URI;
|
||||
|
||||
globalStorageHome: URI;
|
||||
workspaceStorageHome: URI;
|
||||
|
||||
// --- settings sync
|
||||
userDataSyncLogResource: URI;
|
||||
userDataSyncHome: URI;
|
||||
|
||||
@@ -33,6 +33,7 @@ export interface ParsedArgs {
|
||||
trace?: boolean;
|
||||
'trace-category-filter'?: string;
|
||||
'trace-options'?: string;
|
||||
'open-devtools'?: boolean;
|
||||
log?: string;
|
||||
logExtensionHostCommunication?: boolean;
|
||||
'extensions-dir'?: string;
|
||||
@@ -202,6 +203,7 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = {
|
||||
'trace-category-filter': { type: 'string' },
|
||||
'trace-options': { type: 'string' },
|
||||
'force-user-env': { type: 'boolean' },
|
||||
'open-devtools': { type: 'boolean' },
|
||||
|
||||
// {{SQL CARBON EDIT}} Start
|
||||
'command': { type: 'string', alias: 'c', cat: 'o', args: 'command-name', description: localize('commandParameter', 'Name of command to run') },
|
||||
|
||||
@@ -39,9 +39,6 @@ export interface INativeEnvironmentService extends IEnvironmentService {
|
||||
extensionsDownloadPath: string;
|
||||
builtinExtensionsPath: string;
|
||||
|
||||
globalStorageHome: string;
|
||||
workspaceStorageHome: string;
|
||||
|
||||
driverHandle?: string;
|
||||
driverVerbose: boolean;
|
||||
|
||||
@@ -102,10 +99,10 @@ export class EnvironmentService implements INativeEnvironmentService {
|
||||
get machineSettingsResource(): URI { return resources.joinPath(URI.file(path.join(this.userDataPath, 'Machine')), 'settings.json'); }
|
||||
|
||||
@memoize
|
||||
get globalStorageHome(): string { return path.join(this.appSettingsHome.fsPath, 'globalStorage'); }
|
||||
get globalStorageHome(): URI { return URI.joinPath(this.appSettingsHome, 'globalStorage'); }
|
||||
|
||||
@memoize
|
||||
get workspaceStorageHome(): string { return path.join(this.appSettingsHome.fsPath, 'workspaceStorage'); }
|
||||
get workspaceStorageHome(): URI { return URI.joinPath(this.appSettingsHome, 'workspaceStorage'); }
|
||||
|
||||
@memoize
|
||||
get keybindingsResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'keybindings.json'); }
|
||||
|
||||
@@ -56,7 +56,10 @@ export async function readFromStdin(targetPath: string, verbose: boolean): Promi
|
||||
const decoder = iconv.getDecoder(encoding);
|
||||
process.stdin.on('data', chunk => stdinFileStream.write(decoder.write(chunk)));
|
||||
process.stdin.on('end', () => {
|
||||
stdinFileStream.write(decoder.end());
|
||||
const end = decoder.end();
|
||||
if (typeof end === 'string') {
|
||||
stdinFileStream.write(end);
|
||||
}
|
||||
stdinFileStream.end();
|
||||
});
|
||||
process.stdin.on('error', error => stdinFileStream.destroy(error));
|
||||
|
||||
@@ -13,7 +13,6 @@ import { IRequestService, asJson, asText } from 'vs/platform/request/common/requ
|
||||
import { IRequestOptions, IRequestContext, IHeaders } from 'vs/base/parts/request/common/request';
|
||||
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { values } from 'vs/base/common/map';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; // {{SQL CARBON EDIT}}
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
@@ -930,7 +929,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(values(map));
|
||||
return [...map.values()];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IExtensionManifest, IExtension, ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExeBasedExtensionTip } from 'vs/platform/product/common/productService';
|
||||
|
||||
export const EXTENSION_IDENTIFIER_PATTERN = '^([a-z0-9A-Z][a-z0-9-A-Z]*)\\.([a-z0-9A-Z][a-z0-9-A-Z]*)$';
|
||||
export const EXTENSION_IDENTIFIER_REGEX = new RegExp(EXTENSION_IDENTIFIER_PATTERN);
|
||||
@@ -239,7 +238,15 @@ export type IConfigBasedExtensionTip = {
|
||||
readonly configName: string,
|
||||
readonly important: boolean,
|
||||
};
|
||||
export type IExecutableBasedExtensionTip = { extensionId: string } & Omit<Omit<IExeBasedExtensionTip, 'recommendations'>, 'important'>;
|
||||
|
||||
export type IExecutableBasedExtensionTip = {
|
||||
readonly extensionId: string,
|
||||
readonly extensionName: string,
|
||||
readonly isExtensionPack: boolean,
|
||||
readonly exeFriendlyName: string,
|
||||
readonly windowsPath?: string,
|
||||
};
|
||||
|
||||
export type IWorkspaceTips = { readonly remoteSet: string[]; readonly recommendations: string[]; };
|
||||
|
||||
export const IExtensionTipsService = createDecorator<IExtensionTipsService>('IExtensionTipsService');
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user