Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2 (#8911)

* Merge from vscode a234f13c45b40a0929777cb440ee011b7549eed2

* update distro

* fix layering

* update distro

* fix tests
This commit is contained in:
Anthony Dresser
2020-01-22 13:42:37 -08:00
committed by GitHub
parent 977111eb21
commit bd7aac8ee0
895 changed files with 24651 additions and 14520 deletions
-19
View File
@@ -1,19 +0,0 @@
{
"parserOptions": {
"ecmaVersion": 6
},
"env": {
"node": true,
"es6": true,
"browser": true,
"amd": true
},
"rules": {
"no-console": 0,
"no-cond-assign": 0,
"no-unused-vars": "error",
"no-extra-semi": "error",
"semi": "error",
"no-inner-declarations": 0
}
}
@@ -71,6 +71,7 @@ export class BrowserClipboardService implements IClipboardService {
}
readTextSync(): string | undefined {
// eslint-disable-next-line no-sync
return this._vsClipboardService.readTextSync();
}
}
+3 -3
View File
@@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
define(["require", "exports"], function (require) {
define(['require', 'exports'], function (require) {
const jquerylib = require.__$__nodeRequire('jquery');
window['jQuery'] = jquerylib;
@@ -21,8 +21,8 @@ define(["require", "exports"], function (require) {
require.__$__nodeRequire('zone.js');
require.__$__nodeRequire('zone.js/dist/zone-error');
require.__$__nodeRequire('chart.js');
window["Zone"]["__zone_symbol__ignoreConsoleErrorUncaughtError"] = true;
window["Zone"]["__zone_symbol__unhandledPromiseRejectionHandler"] = e => setImmediate(() => {
window['Zone']['__zone_symbol__ignoreConsoleErrorUncaughtError'] = true;
window['Zone']['__zone_symbol__unhandledPromiseRejectionHandler'] = e => setImmediate(() => {
window.dispatchEvent(new PromiseRejectionEvent('unhandledrejection', e));
}); // let window handle this
});
@@ -458,7 +458,7 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements
};
let isUntitled: boolean = uri.scheme === Schemas.untitled;
const fileInput = isUntitled ? this._untitledEditorService.createOrGet(uri, 'notebook', options.initialContent) :
const fileInput = isUntitled ? this._untitledEditorService.create({ associatedResource: uri, mode: 'notebook', initialValue: options.initialContent }) :
this._editorService.createInput({ resource: uri, mode: 'notebook' });
let input: NotebookInput;
if (isUntitled) {
@@ -44,9 +44,10 @@ export class CategoryView extends ViewPane {
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService);
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
}
// we want a fixed size, so when we render to will measure our content and set that to be our
@@ -17,15 +17,15 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { ComponentBase } from 'sql/workbench/browser/modelComponents/componentBase';
import { IComponent, IComponentDescriptor, IModelStore } from 'sql/workbench/browser/modelComponents/interfaces';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SimpleEditorProgressService } from 'vs/editor/standalone/browser/simpleServices';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { TextDiffEditorModel } from 'vs/workbench/common/editor/textDiffEditorModel';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { ITextModel } from 'vs/editor/common/model';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SimpleProgressIndicator } from 'sql/workbench/services/progress/browser/simpleProgressIndicator';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
@Component({
template: `
@@ -69,8 +69,8 @@ export default class DiffEditorComponent extends ComponentBase implements ICompo
}
private _createEditor(): void {
this._instantiationService = this._instantiationService.createChild(new ServiceCollection([IEditorProgressService, new SimpleEditorProgressService()]));
this._editor = this._instantiationService.createInstance(TextDiffEditor);
const customInstan = this._instantiationService.createChild(new ServiceCollection([IEditorProgressService, new SimpleProgressIndicator()]));
this._editor = customInstan.createInstance(TextDiffEditor);
this._editor.reverseColoring();
this._editor.create(this._el.nativeElement);
this._editor.setVisible(true);
@@ -19,11 +19,11 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { ComponentBase } from 'sql/workbench/browser/modelComponents/componentBase';
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/workbench/browser/modelComponents/interfaces';
import { QueryTextEditor } from 'sql/workbench/browser/modelComponents/queryTextEditor';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SimpleEditorProgressService } from 'vs/editor/standalone/browser/simpleServices';
import { IProgressService } from 'vs/platform/progress/common/progress';
import { ILogService } from 'vs/platform/log/common/log';
import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import { SimpleProgressIndicator } from 'sql/workbench/services/progress/browser/simpleProgressIndicator';
@Component({
template: '',
@@ -61,12 +61,12 @@ export default class EditorComponent extends ComponentBase implements IComponent
}
private async _createEditor(): Promise<void> {
let instantiationService = this._instantiationService.createChild(new ServiceCollection([IProgressService, new SimpleEditorProgressService()]));
this._editor = instantiationService.createInstance(QueryTextEditor);
const customInstan = this._instantiationService.createChild(new ServiceCollection([IEditorProgressService, new SimpleProgressIndicator()]));
this._editor = customInstan.createInstance(QueryTextEditor);
this._editor.create(this._el.nativeElement);
this._editor.setVisible(true);
let uri = this.createUri();
this._editorInput = instantiationService.createInstance(UntitledTextEditorInput, uri, false, 'plaintext', '', '');
this._editorInput = this._instantiationService.createInstance(UntitledTextEditorInput, uri, false, 'plaintext', '', '');
await this._editor.setInput(this._editorInput, undefined);
const model = await this._editorInput.resolve();
this._editorModel = model.textEditorModel;
@@ -16,13 +16,13 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService';
import { EditorOptions } from 'vs/workbench/common/editor';
import { StandaloneCodeEditor } from 'vs/editor/standalone/browser/standaloneCodeEditor';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
/**
* Extension of TextResourceEditor that is always readonly rather than only with non UntitledInputs
@@ -56,7 +56,7 @@ export class QueryTextEditor extends BaseTextEditor {
}
public createEditorControl(parent: HTMLElement, configuration: IEditorOptions): editorCommon.IEditor {
return this.instantiationService.createInstance(StandaloneCodeEditor, parent, configuration);
return this.instantiationService.createInstance(CodeEditorWidget, parent, configuration, {});
}
protected getConfigurationOverrides(): IEditorOptions {
@@ -87,8 +87,8 @@ export default class SplitViewContainer extends ContainerBase<FlexItemLayout> im
let c = component as ComponentBase;
let basicView: SplitPane = new SplitPane();
basicView.orientation = orientation;
basicView.element = c.getHtml(),
basicView.component = c;
basicView.element = c.getHtml();
basicView.component = c;
basicView.minimumSize = 50;
basicView.maximumSize = Number.MAX_VALUE;
return basicView;
@@ -62,8 +62,9 @@ export class CustomTreeViewPanel extends ViewPane {
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService
) {
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService);
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
const { treeView } = (<ITreeViewDescriptor>Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).getView(options.id));
this.treeView = treeView as ITreeView;
this._register(this.treeView.onDidChangeActions(() => this.updateActions(), this));
+1 -1
View File
@@ -5,7 +5,7 @@
import { Action } from 'vs/base/common/actions';
import { IOpenerService } from 'vs/platform/opener/common/opener';
//tslint:disable-next-line:layering
// eslint-disable-next-line code-layering
import { IElectronService } from 'vs/platform/electron/node/electron';
import { URI } from 'vs/base/common/uri';
@@ -46,11 +46,11 @@ class AccountPanel extends ViewPane {
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IThemeService private themeService: IThemeService,
@IContextKeyService contextKeyService: IContextKeyService
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService);
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
}
protected renderBody(container: HTMLElement): void {
@@ -294,9 +294,9 @@ export class AccountDialog extends Modal {
this._keybindingService,
this._contextMenuService,
this._configurationService,
this._instantiationService,
this._themeService,
this.contextKeyService
this.contextKeyService,
this._instantiationService
);
attachPanelStyler(providerView, this._themeService);
@@ -72,7 +72,7 @@ export class CreateInsightAction extends Action {
}
};
let input = this.untitledEditorService.createOrGet(undefined, 'json', JSON.stringify(widgetConfig));
let input = this.untitledEditorService.create({ mode: 'json', initialValue: JSON.stringify(widgetConfig) });
return this.editorService.openEditor(input, { pinned: true })
.then(
@@ -155,7 +155,7 @@ export class SaveImageAction extends Action {
if (context.insight instanceof Graph) {
let fileFilters = new Array<FileFilter>({ extensions: ['png'], name: localize('resultsSerializer.saveAsFileExtensionPNGTitle', "PNG") });
const filePath = await this.fileDialogService.pickFileToSave({ filters: fileFilters });
const filePath = await this.fileDialogService.showSaveDialog({ filters: fileFilters });
const data = (<Graph>context.insight).getCanvasData();
if (!data) {
this.notificationService.error(localize('chartNotFound', "Could not find chart to save"));
@@ -10,7 +10,7 @@ import { TestLayoutService } from 'vs/workbench/test/workbenchTestServices';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { SimpleNotificationService } from 'vs/editor/standalone/browser/simpleServices';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
suite('Chart View', () => {
test('initializes without error', () => {
@@ -29,7 +29,7 @@ function createChartView(): ChartView {
const contextViewService = new ContextViewService(layoutService);
const themeService = new TestThemeService();
const instantiationService = new TestInstantiationService();
const notificationService = new SimpleNotificationService();
const notificationService = new TestNotificationService();
instantiationService.stub(IThemeService, themeService);
return new ChartView(contextViewService, themeService, instantiationService, notificationService);
}
@@ -34,7 +34,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput';
import { SimpleUriLabelService } from 'vs/editor/standalone/browser/simpleServices';
import { LabelService } from 'vs/workbench/services/label/common/labelService';
class TestParsedArgs implements ParsedArgs {
[arg: string]: any;
@@ -393,7 +393,7 @@ suite('commandLineService tests', () => {
querymodelService.setup(c => c.onRunQueryComplete).returns(() => Event.None);
const instantiationService = new TestInstantiationService();
let uri = URI.file(args._[0]);
const untitledEditorInput = new UntitledTextEditorInput(uri, false, '', '', '', instantiationService, undefined, new SimpleUriLabelService(), undefined, undefined, undefined);
const untitledEditorInput = new UntitledTextEditorInput(uri, false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
const queryInput = new UntitledQueryEditorInput(undefined, untitledEditorInput, undefined, connectionManagementService.object, querymodelService.object, configurationService.object, undefined);
queryInput.state.connected = true;
const editorService: TypeMoq.Mock<IEditorService> = TypeMoq.Mock.ofType<IEditorService>(TestEditorService, TypeMoq.MockBehavior.Strict);
@@ -1,33 +0,0 @@
<!--
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-->
<div class="fullsize" style="display: flex; flex-direction: column">
<div scrollable [horizontalScroll]="ScrollbarVisibility.Auto" [verticalScroll]="ScrollbarVisibility.Auto">
<table class="grid-table">
<tr *ngFor="let row of rows" class="grid-table-row">
<ng-container *ngFor="let col of cols">
<ng-container *ngIf="getContent(row,col) !== undefined">
<td class="table-cell" [colSpan]=getColspan(row,col) [rowSpan]=getRowspan(row,col)
[width]="getWidgetWidth(row,col)" [height]="getWidgetHeight(row,col)">
<dashboard-widget-wrapper *ngIf="isWidget(row,col)" [_config]="getWidgetContent(row,col)"
style="position:absolute;" [style.width]="getWidgetWidth(row,col)"
[style.height]="getWidgetHeight(row,col)">
</dashboard-widget-wrapper>
<webview-content *ngIf="isWebview(row,col)" [webviewId]="getWebviewId(row,col)">
</webview-content>
<modelview-content *ngIf="isModelView(row,col)" [modelViewId]="getModelViewId(row,col)">
</modelview-content>
</td>
</ng-container>
</ng-container>
</tr>
</table>
</div>
</div>
@@ -15,10 +15,10 @@ import { WebviewContent } from 'sql/workbench/contrib/dashboard/browser/contents
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { Event, Emitter } from 'vs/base/common/event';
import { ScrollbarVisibility } from 'vs/editor/common/standalone/standaloneEnums';
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
import { values } from 'vs/base/common/collections';
import { fill } from 'vs/base/common/arrays';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
export interface GridCellConfig {
id?: string;
@@ -46,7 +46,35 @@ export interface GridModelViewConfig extends GridCellConfig {
@Component({
selector: 'dashboard-grid-container',
templateUrl: decodeURI(require.toUrl('./dashboardGridContainer.component.html')),
template: `
<div class="fullsize" style="display: flex; flex-direction: column">
<div scrollable [horizontalScroll]="${ScrollbarVisibility.Auto}" [verticalScroll]="${ScrollbarVisibility.Auto}">
<table class="grid-table">
<tr *ngFor="let row of rows" class="grid-table-row">
<ng-container *ngFor="let col of cols">
<ng-container *ngIf="getContent(row,col) !== undefined">
<td class="table-cell" [colSpan]=getColspan(row,col) [rowSpan]=getRowspan(row,col)
[width]="getWidgetWidth(row,col)" [height]="getWidgetHeight(row,col)">
<dashboard-widget-wrapper *ngIf="isWidget(row,col)" [_config]="getWidgetContent(row,col)"
style="position:absolute;" [style.width]="getWidgetWidth(row,col)"
[style.height]="getWidgetHeight(row,col)">
</dashboard-widget-wrapper>
<webview-content *ngIf="isWebview(row,col)" [webviewId]="getWebviewId(row,col)">
</webview-content>
<modelview-content *ngIf="isModelView(row,col)" [modelViewId]="getModelViewId(row,col)">
</modelview-content>
</td>
</ng-container>
</ng-container>
</tr>
</table>
</div>
</div>
`,
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardGridContainer) }]
})
export class DashboardGridContainer extends DashboardTab implements OnDestroy {
@@ -56,7 +84,6 @@ export class DashboardGridContainer extends DashboardTab implements OnDestroy {
public readonly onResize: Event<void> = this._onResize.event;
private cellWidth: number = 270;
private cellHeight: number = 270;
public ScrollbarVisibility = ScrollbarVisibility;
protected SKELETON_WIDTH = 5;
@@ -17,14 +17,14 @@ import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.d
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ScrollbarVisibility } from 'vs/editor/common/standalone/standaloneEnums';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
@Component({
selector: 'dashboard-home-container',
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardHomeContainer) }],
template: `
<div class="fullsize" style="display: flex; flex-direction: column">
<div scrollable [horizontalScroll]="ScrollbarVisibility.Hidden" [verticalScroll]="ScrollbarVisibility.Auto">
<div scrollable [horizontalScroll]="${ScrollbarVisibility.Hidden}" [verticalScroll]="${ScrollbarVisibility.Auto}">
<dashboard-widget-wrapper #propertiesClass *ngIf="properties" [collapsable]="true" [_config]="properties"
style="padding-left: 10px; padding-right: 10px; display: block; flex: 0" [style.height.px]="_propertiesClass?.collapsed ? '30' : '90'">
</dashboard-widget-wrapper>
@@ -39,8 +39,6 @@ export class DashboardHomeContainer extends DashboardWidgetContainer {
@ViewChild('propertiesClass') private _propertiesClass: DashboardWidgetWrapper;
@ContentChild(ScrollableDirective) private _scrollable: ScrollableDirective;
public ScrollbarVisibility = ScrollbarVisibility;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef,
@Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: DashboardServiceInterface,
@@ -35,12 +35,12 @@ export class ConnectionViewletPanel extends ViewPane {
private options: IViewletViewOptions,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IInstantiationService instantiationService: IInstantiationService,
@IConfigurationService configurationService: IConfigurationService,
@IObjectExplorerService private readonly objectExplorerService: IObjectExplorerService,
@IContextKeyService contextKeyService: IContextKeyService
) {
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService);
super({ ...(options as IViewPaneOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
this._addServerAction = this.instantiationService.createInstance(AddServerAction,
AddServerAction.ID,
AddServerAction.LABEL);
@@ -16,6 +16,7 @@ import { coalesce } from 'vs/base/common/arrays';
import { CustomTreeViewPanel, CustomTreeView } from 'sql/workbench/browser/parts/views/customView';
import { VIEWLET_ID } from 'sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
interface IUserFriendlyViewDescriptor {
id: string;
@@ -105,11 +106,13 @@ export class DataExplorerContainerExtensionHandler implements IWorkbenchContribu
const viewDescriptor = <ITreeViewDescriptor>{
id: item.id,
name: item.name,
ctorDescriptor: { ctor: CustomTreeViewPanel },
ctorDescriptor: new SyncDescriptor(CustomTreeViewPanel),
when: ContextKeyExpr.deserialize(item.when),
canToggleVisibility: true,
collapsed: this.showCollapsed(container),
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, item.name, container)
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, item.name, container),
extensionId: extension.description.identifier,
originalContainerId: entry.key
};
viewIds.push(viewDescriptor.id);
@@ -129,15 +132,15 @@ export class DataExplorerContainerExtensionHandler implements IWorkbenchContribu
for (let descriptor of viewDescriptors) {
if (typeof descriptor.id !== 'string') {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", "id"));
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'id'));
return false;
}
if (typeof descriptor.name !== 'string') {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", "name"));
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'name'));
return false;
}
if (descriptor.when && typeof descriptor.when !== 'string') {
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", "when"));
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
return false;
}
}
@@ -27,6 +27,7 @@ import { ShowViewletAction, Viewlet } from 'vs/workbench/browser/viewlet';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ViewPaneContainer, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
export const VIEWLET_ID = 'workbench.view.connections';
@@ -62,7 +63,7 @@ export class DataExplorerViewletViewsContribution implements IWorkbenchContribut
return {
id: ConnectionViewletPanel.ID,
name: localize('dataExplorer.servers', "Servers"),
ctorDescriptor: { ctor: ConnectionViewletPanel },
ctorDescriptor: new SyncDescriptor(ConnectionViewletPanel),
weight: 100,
canToggleVisibility: true,
order: 0
@@ -159,6 +160,6 @@ export class DataExplorerViewPaneContainer extends ViewPaneContainer {
export const VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({
id: VIEWLET_ID,
name: localize('dataexplorer.name', "Connections"),
ctorDescriptor: { ctor: DataExplorerViewPaneContainer },
ctorDescriptor: new SyncDescriptor(DataExplorerViewPaneContainer),
icon: 'dataExplorer'
}, ViewContainerLocation.Sidebar);
@@ -217,7 +217,6 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
return this._connectionManagementService.getTabColorForUri(this.uri);
}
public get onDidModelChangeContent(): Event<void> { return this._sql.onDidModelChangeContent; }
public get onDidModelChangeEncoding(): Event<void> { return this._sql.onDidModelChangeEncoding; }
public resolve(refresh?: boolean): Promise<EditorModel> { return this._sql.resolve(); }
public getEncoding(): string { return this._sql.getEncoding(); }
@@ -15,9 +15,6 @@ import { NotebookModel } from 'sql/workbench/contrib/notebook/browser/models/not
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import * as themeColors from 'vs/workbench/common/theme';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SimpleEditorProgressService } from 'vs/editor/standalone/browser/simpleServices';
import { IProgressService } from 'vs/platform/progress/common/progress';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITextModel } from 'vs/editor/common/model';
import * as DOM from 'vs/base/browser/dom';
@@ -35,6 +32,9 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { CellView } from 'sql/workbench/contrib/notebook/browser/cellViews/interfaces';
import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput';
import { UntitledTextEditorModel } from 'vs/workbench/common/editor/untitledTextEditorModel';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import { SimpleProgressIndicator } from 'sql/workbench/services/progress/browser/simpleProgressIndicator';
export const CODE_SELECTOR: string = 'code-component';
const MARKDOWN_CLASS = 'markdown';
@@ -200,8 +200,8 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
}
private async createEditor(): Promise<void> {
let instantiationService = this._instantiationService.createChild(new ServiceCollection([IProgressService, new SimpleEditorProgressService()]));
this._editor = instantiationService.createInstance(QueryTextEditor);
const customInstan = this._instantiationService.createChild(new ServiceCollection([IEditorProgressService, new SimpleProgressIndicator()]));
this._editor = customInstan.createInstance(QueryTextEditor);
this._editor.create(this.codeElement.nativeElement);
this._editor.setVisible(true);
this._editor.setMinimumHeight(this._minimumHeight);
@@ -210,7 +210,7 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
let uri = this.cellModel.cellUri;
let cellModelSource: string;
cellModelSource = Array.isArray(this.cellModel.source) ? this.cellModel.source.join('') : this.cellModel.source;
this._editorInput = instantiationService.createInstance(UntitledTextEditorInput, uri, false, this.cellModel.language, cellModelSource, '');
this._editorInput = this._instantiationService.createInstance(UntitledTextEditorInput, uri, false, this.cellModel.language, cellModelSource, '');
await this._editor.setInput(this._editorInput, undefined);
this.setFocusAndScroll();
@@ -16,7 +16,7 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { INotebookModel, IContentManager, NotebookContentChange } from 'sql/workbench/contrib/notebook/browser/models/modelInterfaces';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { Schemas } from 'vs/base/common/network';
import { StateChange, ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { LocalContentManager } from 'sql/workbench/services/notebook/common/localContentManager';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
@@ -73,12 +73,14 @@ export class NotebookEditorModel extends EditorModel {
}));
} else {
if (this.textEditorModel instanceof TextFileEditorModel) {
this._register(this.textEditorModel.onDidStateChange(change => {
this._register(this.textEditorModel.onDidSave(() => {
let dirty = this.textEditorModel instanceof ResourceEditorModel ? false : this.textEditorModel.isDirty();
this.setDirty(dirty);
this.sendNotebookSerializationStateChange();
}));
this._register(this.textEditorModel.onDidChangeDirty(() => {
let dirty = this.textEditorModel instanceof ResourceEditorModel ? false : this.textEditorModel.isDirty();
this.setDirty(dirty);
if (change === StateChange.SAVED) {
this.sendNotebookSerializationStateChange();
}
}));
}
}
@@ -14,12 +14,11 @@ import { UntitledNotebookInput } from 'sql/workbench/contrib/notebook/common/mod
import { FileNotebookInput } from 'sql/workbench/contrib/notebook/common/models/fileNotebookInput';
import { FileNoteBookEditorInputFactory, UntitledNoteBookEditorInputFactory, NotebookEditorInputAssociation } from 'sql/workbench/contrib/notebook/common/models/nodebookInputFactory';
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionsExtensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor, registerAction, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { SyncActionDescriptor, registerAction2, MenuRegistry, MenuId, Action2 } from 'vs/platform/actions/common/actions';
import { NotebookEditor } from 'sql/workbench/contrib/notebook/browser/notebookEditor';
import { NewNotebookAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
import { KeyMod } from 'vs/editor/common/standalone/standaloneBase';
import { KeyCode } from 'vs/base/common/keyCodes';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IConfigurationRegistry, Extensions as ConfigExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { GridOutputComponent } from 'sql/workbench/contrib/notebook/browser/outputs/gridOutput.component';
import { PlotlyOutputComponent } from 'sql/workbench/contrib/notebook/browser/outputs/plotlyOutput.component';
@@ -131,9 +130,15 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerWidgetContext, {
order: 1
});
registerAction({
id: 'workbench.action.setWorkspaceAndOpen',
handler: async (accessor, options: { forceNewWindow: boolean, folderPath: URI }) => {
registerAction2(class extends Action2 {
constructor() {
super({
id: 'workbench.action.setWorkspaceAndOpen',
title: localize('workbench.action.setWorkspaceAndOpen', "Set Workspace And Open")
});
}
run = async (accessor, options: { forceNewWindow: boolean, folderPath: URI }) => {
const viewletService = accessor.get(IViewletService);
const workspaceEditingService = accessor.get(IWorkspaceEditingService);
const hostService = accessor.get(IHostService);
@@ -150,7 +155,7 @@ registerAction({
else {
return hostService.reload();
}
}
};
});
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigExtensions.Configuration);
@@ -167,14 +172,6 @@ configurationRegistry.registerConfiguration({
}
});
registerAction({
id: 'workbench.books.action.focusBooksExplorer',
handler: async (accessor) => {
const viewletService = accessor.get(IViewletService);
viewletService.openViewlet('workbench.view.extension.books-explorer', true);
}
});
/* *************** Output components *************** */
// Note: most existing types use the same component to render. In order to
// preserve correct rank order, we register it once for each different rank of
@@ -142,8 +142,8 @@ suite('Notebook Editor Model', function (): void {
});
teardown(() => {
if (accessor && accessor.textFileService && accessor.textFileService.models) {
(<TextFileEditorModelManager>accessor.textFileService.models).clear();
if (accessor && accessor.textFileService && accessor.textFileService.files) {
(<TextFileEditorModelManager>accessor.textFileService.files).clear();
}
});
@@ -870,7 +870,7 @@ suite('Notebook Editor Model', function (): void {
async function createTextEditorModel(self: Mocha.ITestCallbackContext): Promise<NotebookEditorModel> {
let textFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(self, defaultUri.toString()), 'utf8', undefined);
(<TextFileEditorModelManager>accessor.textFileService.models).add(textFileEditorModel.resource, textFileEditorModel);
(<TextFileEditorModelManager>accessor.textFileService.files).add(textFileEditorModel.resource, textFileEditorModel);
await textFileEditorModel.load();
return new NotebookEditorModel(defaultUri, textFileEditorModel, mockNotebookService.object, testResourcePropertiesService);
}
@@ -16,10 +16,10 @@ import { UntitledTextEditorModel } from 'vs/workbench/common/editor/untitledText
import { NodeStub, NotebookServiceStub } from 'sql/workbench/contrib/notebook/test/stubs';
import { basenameOrAuthority } from 'vs/base/common/resources';
import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput';
import { SimpleUriLabelService } from 'vs/editor/standalone/browser/simpleServices';
import { IExtensionService, NullExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { INotebookService, IProviderInfo } from 'sql/workbench/services/notebook/browser/notebookService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { LabelService } from 'vs/workbench/services/label/common/labelService';
suite('Notebook Input', function (): void {
const instantiationService = workbenchInstantiationService();
@@ -48,7 +48,7 @@ suite('Notebook Input', function (): void {
let untitledNotebookInput: UntitledNotebookInput;
setup(() => {
untitledTextInput = new UntitledTextEditorInput(untitledUri, false, '', '', '', instantiationService, undefined, new SimpleUriLabelService(), undefined, undefined, undefined);
untitledTextInput = new UntitledTextEditorInput(untitledUri, false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
untitledNotebookInput = new UntitledNotebookInput(
testTitle, untitledUri, untitledTextInput,
undefined, instantiationService, mockNotebookService.object, mockExtensionService.object);
@@ -169,7 +169,7 @@ suite('Notebook Input', function (): void {
assert.ok(untitledNotebookInput.matches(untitledNotebookInput), 'Input should match itself.');
let otherTestUri = URI.from({ scheme: Schemas.untitled, path: 'OtherTestPath' });
let otherTextInput = new UntitledTextEditorInput(otherTestUri, false, '', '', '', instantiationService, undefined, new SimpleUriLabelService(), undefined, undefined, undefined);
let otherTextInput = new UntitledTextEditorInput(otherTestUri, false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
let otherInput = instantiationService.createInstance(UntitledNotebookInput, 'OtherTestInput', otherTestUri, otherTextInput);
assert.strictEqual(untitledNotebookInput.matches(otherInput), false, 'Input should not match different input.');
@@ -516,7 +516,7 @@ export class NodeStub implements Node {
get parentNode(): Node & ParentNode {
throw new Error('Method not implemented.');
}
get previousSibling(): Node {
get previousSibling(): ChildNode {
throw new Error('Method not implemented.');
}
nodeValue: string;
@@ -16,13 +16,13 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService';
import { EditorOptions } from 'vs/workbench/common/editor';
import { StandaloneCodeEditor } from 'vs/editor/standalone/browser/standaloneCodeEditor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
class ProfilerResourceCodeEditor extends StandaloneCodeEditor {
class ProfilerResourceCodeEditor extends CodeEditorWidget {
// protected _getContributions(): IEditorContributionCtor[] {
// let contributions = super._getContributions();
@@ -53,7 +53,7 @@ export class ProfilerResourceEditor extends BaseTextEditor {
}
public createEditorControl(parent: HTMLElement, configuration: IEditorOptions): editorCommon.IEditor {
return this.instantiationService.createInstance(ProfilerResourceCodeEditor, parent, configuration);
return this.instantiationService.createInstance(ProfilerResourceCodeEditor, parent, configuration, {});
}
protected getConfigurationOverrides(): IEditorOptions {
@@ -579,7 +579,7 @@ export abstract class GridTableBase<T> extends Disposable implements IView {
let value = d.resultSubset.rows[0][event.cell.cell - 1];
let content = value.displayValue;
const input = this.untitledEditorService.createOrGet(undefined, column.isXml ? 'xml' : 'json', content);
const input = this.untitledEditorService.create({ mode: column.isXml ? 'xml' : 'json', initialValue: content });
const model = await input.resolve();
await this.instantiationService.invokeFunction(formatDocumentWithSelectedProvider, model.textEditorModel, FormattingMode.Explicit, CancellationToken.None);
return this.editorService.openEditor(input);
@@ -21,7 +21,6 @@ export class UntitledQueryEditorInput extends QueryEditorInput implements IEncod
public static readonly ID = 'workbench.editorInput.untitledQueryInput';
public readonly onDidModelChangeContent = this.text.onDidModelChangeContent;
public readonly onDidModelChangeEncoding = this.text.onDidModelChangeEncoding;
constructor(
@@ -33,7 +33,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/
import { TestConnectionManagementService } from 'sql/platform/connection/test/common/testConnectionManagementService';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput';
import { SimpleUriLabelService } from 'vs/editor/standalone/browser/simpleServices';
import { LabelService } from 'vs/workbench/services/label/common/labelService';
suite('SQL QueryAction Tests', () => {
@@ -70,7 +70,7 @@ suite('SQL QueryAction Tests', () => {
connectionManagementService = TypeMoq.Mock.ofType<TestConnectionManagementService>(TestConnectionManagementService);
connectionManagementService.setup(q => q.onDisconnect).returns(() => Event.None);
const instantiationService = new TestInstantiationService();
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new SimpleUriLabelService(), undefined, undefined, undefined);
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
// Setup a reusable mock QueryInput
testQueryInput = TypeMoq.Mock.ofType(UntitledQueryEditorInput, TypeMoq.MockBehavior.Strict, undefined, fileInput, undefined, connectionManagementService.object, queryModelService.object, configurationService.object);
testQueryInput.setup(x => x.uri).returns(() => testUri);
@@ -175,7 +175,7 @@ suite('SQL QueryAction Tests', () => {
queryModelService.setup(x => x.onRunQueryStart).returns(() => Event.None);
queryModelService.setup(x => x.onRunQueryComplete).returns(() => Event.None);
const instantiationService = new TestInstantiationService();
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new SimpleUriLabelService(), undefined, undefined, undefined);
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
// ... Mock "isSelectionEmpty" in QueryEditor
let queryInput = TypeMoq.Mock.ofType(UntitledQueryEditorInput, TypeMoq.MockBehavior.Strict, undefined, fileInput, undefined, connectionManagementService.object, queryModelService.object, configurationService.object);
@@ -224,7 +224,7 @@ suite('SQL QueryAction Tests', () => {
// ... Mock "getSelection" in QueryEditor
const instantiationService = new TestInstantiationService();
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new SimpleUriLabelService(), undefined, undefined, undefined);
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
let queryInput = TypeMoq.Mock.ofType(UntitledQueryEditorInput, TypeMoq.MockBehavior.Loose, undefined, fileInput, undefined, connectionManagementService.object, queryModelService.object, configurationService.object);
queryInput.setup(x => x.uri).returns(() => testUri);
@@ -24,7 +24,7 @@ import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledText
import { UntitledQueryEditorInput } from 'sql/workbench/contrib/query/common/untitledQueryEditorInput';
import { TestQueryModelService } from 'sql/platform/query/test/common/testQueryModelService';
import { Event } from 'vs/base/common/event';
import { SimpleUriLabelService } from 'vs/editor/standalone/browser/simpleServices';
import { LabelService } from 'vs/workbench/services/label/common/labelService';
suite('SQL QueryEditor Tests', () => {
let instantiationService: TypeMoq.Mock<InstantiationService>;
@@ -285,7 +285,7 @@ suite('SQL QueryEditor Tests', () => {
return new RunQueryAction(undefined, undefined, undefined);
});
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService.object, undefined, new SimpleUriLabelService(), undefined, undefined, undefined);
let fileInput = new UntitledTextEditorInput(URI.parse('file://testUri'), false, '', '', '', instantiationService.object, undefined, new LabelService(undefined, undefined), undefined, undefined, undefined);
queryModelService = TypeMoq.Mock.ofType(TestQueryModelService, TypeMoq.MockBehavior.Strict);
queryModelService.setup(x => x.disposeQuery(TypeMoq.It.isAny()));
queryModelService.setup(x => x.onRunQueryComplete).returns(() => Event.None);
@@ -8,7 +8,7 @@ import { localize } from 'vs/nls';
import { Disposable } from 'vs/base/common/lifecycle';
import { Table } from 'sql/base/browser/ui/table/table';
import { PlanXmlParser } from 'sql/workbench/contrib/queryPlan/common/planXmlParser';
import { PlanXmlParser } from 'sql/workbench/contrib/queryPlan/browser/planXmlParser';
import { IPanelView, IPanelTab } from 'sql/base/browser/ui/panel/panel';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachTableStyler } from 'sql/platform/theme/common/styler';
@@ -62,9 +62,10 @@ class InsightTableView<T> extends ViewPane {
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService);
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, instantiationService);
}
protected renderBody(container: HTMLElement): void {
@@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IProgressIndicator, IProgressRunner } from 'vs/platform/progress/common/progress';
export class SimpleProgressIndicator implements IProgressIndicator {
show(infinite: true, delay?: number): IProgressRunner;
show(total: number, delay?: number): IProgressRunner;
show(total: any, delay?: any) {
return {
total: (total: number) => {
},
worked: (worked: number) => {
},
done: () => {
}
};
}
async showWhile(promise: Promise<any>, delay?: number): Promise<void> {
try {
await promise;
} catch (e) {
}
}
_serviceBrand: undefined;
}
@@ -52,7 +52,7 @@ export class QueryEditorService implements IQueryEditorService {
let docUri: URI = URI.from({ scheme: Schemas.untitled, path: filePath });
// Create a sql document pane with accoutrements
const fileInput = this._untitledEditorService.createOrGet(docUri, 'sql');
const fileInput = this._untitledEditorService.create({ associatedResource: docUri, mode: 'sql' });
let untitledEditorModel = await fileInput.resolve();
if (sqlContent) {
untitledEditorModel.textEditorModel.setValue(sqlContent);
@@ -87,7 +87,7 @@ export class QueryEditorService implements IQueryEditorService {
let docUri: URI = URI.from({ scheme: Schemas.untitled, path: filePath });
// Create a sql document pane with accoutrements
const fileInput = this._untitledEditorService.createOrGet(docUri, 'sql');
const fileInput = this._untitledEditorService.create({ associatedResource: docUri, mode: 'sql' });
const m = await fileInput.resolve();
if (sqlContent) {
m.textEditorModel.setValue(sqlContent);
+1 -5
View File
@@ -25,10 +25,6 @@
"./sql"
],
"exclude": [
"./typings/es6-promise.d.ts",
"./typings/require-monaco.d.ts",
"./typings/xterm.d.ts",
"./typings/xterm-addon-search.d.ts",
"./typings/xterm-addon-web-links.d.ts"
"./typings/es6-promise.d.ts"
]
}
+1 -1
View File
@@ -12,7 +12,7 @@ interface Map<K, V> {
forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void;
get(key: K): V | undefined;
has(key: K): boolean;
set(key: K, value?: V): Map<K, V>;
set(key: K, value: V): Map<K, V>;
readonly size: number;
// not supported on IE11:
+1 -1
View File
@@ -31,7 +31,7 @@ declare class LoaderEvent {
readonly detail: string;
}
declare var define: {
declare const define: {
(moduleName: string, dependencies: string[], callback: (...args: any[]) => any): any;
(moduleName: string, dependencies: string[], definition: any): any;
(moduleName: string, callback: (...args: any[]) => any): any;
+32 -22
View File
@@ -12,6 +12,7 @@ import { BrowserFeatures } from 'vs/base/browser/canIUse';
export interface IStandardMouseMoveEventData {
leftButton: boolean;
buttons: number;
posx: number;
posy: number;
}
@@ -33,21 +34,22 @@ export function standardMouseMoveMerger(lastEvent: IStandardMouseMoveEventData |
ev.preventDefault();
return {
leftButton: ev.leftButton,
buttons: ev.buttons,
posx: ev.posx,
posy: ev.posy
};
}
export class GlobalMouseMoveMonitor<R> implements IDisposable {
export class GlobalMouseMoveMonitor<R extends { buttons: number; }> implements IDisposable {
protected readonly hooks = new DisposableStore();
protected mouseMoveEventMerger: IEventMerger<R> | null = null;
protected mouseMoveCallback: IMouseMoveCallback<R> | null = null;
protected onStopCallback: IOnStopCallback | null = null;
private readonly _hooks = new DisposableStore();
private _mouseMoveEventMerger: IEventMerger<R> | null = null;
private _mouseMoveCallback: IMouseMoveCallback<R> | null = null;
private _onStopCallback: IOnStopCallback | null = null;
public dispose(): void {
this.stopMonitoring(false);
this.hooks.dispose();
this._hooks.dispose();
}
public stopMonitoring(invokeStopCallback: boolean): void {
@@ -57,11 +59,11 @@ export class GlobalMouseMoveMonitor<R> implements IDisposable {
}
// Unhook
this.hooks.clear();
this.mouseMoveEventMerger = null;
this.mouseMoveCallback = null;
const onStopCallback = this.onStopCallback;
this.onStopCallback = null;
this._hooks.clear();
this._mouseMoveEventMerger = null;
this._mouseMoveCallback = null;
const onStopCallback = this._onStopCallback;
this._onStopCallback = null;
if (invokeStopCallback && onStopCallback) {
onStopCallback();
@@ -69,10 +71,11 @@ export class GlobalMouseMoveMonitor<R> implements IDisposable {
}
public isMonitoring(): boolean {
return !!this.mouseMoveEventMerger;
return !!this._mouseMoveEventMerger;
}
public startMonitoring(
initialButtons: number,
mouseMoveEventMerger: IEventMerger<R>,
mouseMoveCallback: IMouseMoveCallback<R>,
onStopCallback: IOnStopCallback
@@ -81,40 +84,47 @@ export class GlobalMouseMoveMonitor<R> implements IDisposable {
// I am already hooked
return;
}
this.mouseMoveEventMerger = mouseMoveEventMerger;
this.mouseMoveCallback = mouseMoveCallback;
this.onStopCallback = onStopCallback;
this._mouseMoveEventMerger = mouseMoveEventMerger;
this._mouseMoveCallback = mouseMoveCallback;
this._onStopCallback = onStopCallback;
let windowChain = IframeUtils.getSameOriginWindowChain();
const mouseMove = platform.isIOS && BrowserFeatures.pointerEvents ? 'pointermove' : 'mousemove';
const mouseUp = platform.isIOS && BrowserFeatures.pointerEvents ? 'pointerup' : 'mouseup';
for (const element of windowChain) {
this.hooks.add(dom.addDisposableThrottledListener(element.window.document, mouseMove,
(data: R) => this.mouseMoveCallback!(data),
(lastEvent: R | null, currentEvent) => this.mouseMoveEventMerger!(lastEvent, currentEvent as MouseEvent)
this._hooks.add(dom.addDisposableThrottledListener(element.window.document, mouseMove,
(data: R) => {
if (data.buttons !== initialButtons) {
// Buttons state has changed in the meantime
this.stopMonitoring(true);
return;
}
this._mouseMoveCallback!(data);
},
(lastEvent: R | null, currentEvent) => this._mouseMoveEventMerger!(lastEvent, currentEvent as MouseEvent)
));
this.hooks.add(dom.addDisposableListener(element.window.document, mouseUp, (e: MouseEvent) => this.stopMonitoring(true)));
this._hooks.add(dom.addDisposableListener(element.window.document, mouseUp, (e: MouseEvent) => this.stopMonitoring(true)));
}
if (IframeUtils.hasDifferentOriginAncestor()) {
let lastSameOriginAncestor = windowChain[windowChain.length - 1];
// We might miss a mouse up if it happens outside the iframe
// This one is for Chrome
this.hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseout', (browserEvent: MouseEvent) => {
this._hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseout', (browserEvent: MouseEvent) => {
let e = new StandardMouseEvent(browserEvent);
if (e.target.tagName.toLowerCase() === 'html') {
this.stopMonitoring(true);
}
}));
// This one is for FF
this.hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseover', (browserEvent: MouseEvent) => {
this._hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document, 'mouseover', (browserEvent: MouseEvent) => {
let e = new StandardMouseEvent(browserEvent);
if (e.target.tagName.toLowerCase() === 'html') {
this.stopMonitoring(true);
}
}));
// This one is for IE
this.hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document.body, 'mouseleave', (browserEvent: MouseEvent) => {
this._hooks.add(dom.addDisposableListener(lastSameOriginAncestor.window.document.body, 'mouseleave', (browserEvent: MouseEvent) => {
this.stopMonitoring(true);
}));
}
+3
View File
@@ -12,6 +12,7 @@ export interface IMouseEvent {
readonly leftButton: boolean;
readonly middleButton: boolean;
readonly rightButton: boolean;
readonly buttons: number;
readonly target: HTMLElement;
readonly detail: number;
readonly posx: number;
@@ -33,6 +34,7 @@ export class StandardMouseEvent implements IMouseEvent {
public readonly leftButton: boolean;
public readonly middleButton: boolean;
public readonly rightButton: boolean;
public readonly buttons: number;
public readonly target: HTMLElement;
public detail: number;
public readonly posx: number;
@@ -49,6 +51,7 @@ export class StandardMouseEvent implements IMouseEvent {
this.leftButton = e.button === 0;
this.middleButton = e.button === 1;
this.rightButton = e.button === 2;
this.buttons = e.buttons;
this.target = <HTMLElement>e.target;
+1 -1
View File
@@ -130,7 +130,7 @@ export class Button extends Disposable {
applyStyles(): void {
if (this._element) {
const background = this.buttonBackground ? this.buttonBackground.toString() : '';
const foreground = this.buttonForeground ? this.buttonForeground.toString() : null;
const foreground = this.buttonForeground ? this.buttonForeground.toString() : '';
const border = this.buttonBorder ? this.buttonBorder.toString() : '';
this._element.style.color = foreground;
+1 -1
View File
@@ -220,7 +220,7 @@ export class SimpleCheckbox extends Widget {
}
protected applyStyles(): void {
this.domNode.style.color = this.styles.checkboxForeground ? this.styles.checkboxForeground.toString() : null;
this.domNode.style.color = this.styles.checkboxForeground ? this.styles.checkboxForeground.toString() : '';
this.domNode.style.backgroundColor = this.styles.checkboxBackground ? this.styles.checkboxBackground.toString() : '';
this.domNode.style.borderColor = this.styles.checkboxBorder ? this.styles.checkboxBorder.toString() : '';
}
@@ -5,7 +5,7 @@
@font-face {
font-family: "codicon";
src: url("./codicon.ttf?17db7f5e5f31fd546e62218bb0823c0c") format("truetype");
src: url("./codicon.ttf?ed926e87ee4e27771159d875e877f74a") format("truetype");
}
.codicon[class*='codicon-'] {
@@ -409,4 +409,5 @@
.codicon-call-outgoing:before { content: "\eb93" }
.codicon-menu:before { content: "\eb94" }
.codicon-expand-all:before { content: "\eb95" }
.codicon-feedback:before { content: "\eb96" }
.codicon-debug-alt:before { content: "\f101" }
+4
View File
@@ -392,6 +392,8 @@ class BranchNode implements ISplitView<ILayoutContext>, IDisposable {
const child = this._removeChild(from);
this._addChild(child, to);
this.onDidChildrenChange();
}
swapChildren(from: number, to: number): void {
@@ -408,6 +410,8 @@ class BranchNode implements ISplitView<ILayoutContext>, IDisposable {
this.splitview.swapViews(from, to);
[this.children[from].orthogonalStartSash, this.children[from].orthogonalEndSash, this.children[to].orthogonalStartSash, this.children[to].orthogonalEndSash] = [this.children[to].orthogonalStartSash, this.children[to].orthogonalEndSash, this.children[from].orthogonalStartSash, this.children[from].orthogonalEndSash];
[this.children[from], this.children[to]] = [this.children[to], this.children[from]];
this.onDidChildrenChange();
}
resizeChild(index: number, size: number): void {
@@ -10,6 +10,7 @@ import { escape } from 'vs/base/common/strings';
export interface IHighlight {
start: number;
end: number;
extraClasses?: string;
}
export class HighlightedLabel {
@@ -69,7 +70,11 @@ export class HighlightedLabel {
htmlContent += '</span>';
pos = highlight.end;
}
htmlContent += '<span class="highlight">';
if (highlight.extraClasses) {
htmlContent += `<span class="highlight ${highlight.extraClasses}">`;
} else {
htmlContent += `<span class="highlight">`;
}
const substring = this.text.substring(highlight.start, highlight.end);
htmlContent += this.supportCodicons ? renderCodicons(escape(substring)) : escape(substring);
htmlContent += '</span>';
+1 -1
View File
@@ -511,7 +511,7 @@ export class InputBox extends Widget {
const styles = this.stylesForType(this.message.type);
spanElement.style.backgroundColor = styles.background ? styles.background.toString() : '';
spanElement.style.color = styles.foreground ? styles.foreground.toString() : null;
spanElement.style.color = styles.foreground ? styles.foreground.toString() : '';
spanElement.style.border = styles.border ? `1px solid ${styles.border}` : '';
dom.append(div, spanElement);
+3 -3
View File
@@ -597,12 +597,12 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
const border = isSelected && this.menuStyle.selectionBorderColor ? `thin solid ${this.menuStyle.selectionBorderColor}` : '';
if (this.item) {
this.item.style.color = fgColor ? `${fgColor}` : null;
this.item.style.backgroundColor = bgColor ? `${bgColor}` : '';
this.item.style.color = fgColor ? fgColor.toString() : '';
this.item.style.backgroundColor = bgColor ? bgColor.toString() : '';
}
if (this.check) {
this.check.style.color = fgColor ? `${fgColor}` : '';
this.check.style.color = fgColor ? fgColor.toString() : '';
}
if (this.container) {
@@ -20,6 +20,7 @@ import { INewScrollPosition, Scrollable, ScrollbarVisibility } from 'vs/base/com
const MOUSE_DRAG_RESET_DISTANCE = 140;
export interface ISimplifiedMouseEvent {
buttons: number;
posx: number;
posy: number;
}
@@ -222,6 +223,7 @@ export abstract class AbstractScrollbar extends Widget {
this.slider.toggleClassName('active', true);
this._mouseMoveMonitor.startMonitoring(
e.buttons,
standardMouseMoveMerger,
(mouseMoveData: IStandardMouseMoveEventData) => {
const mouseOrthogonalPosition = this._sliderOrthogonalMousePosition(mouseMoveData);
@@ -93,6 +93,7 @@ export class ScrollbarArrow extends Widget {
this._mousedownScheduleRepeatTimer.cancelAndSet(scheduleRepeater, 200);
this._mouseMoveMonitor.startMonitoring(
e.buttons,
standardMouseMoveMerger,
(mouseMoveData: IStandardMouseMoveEventData) => {
/* Intentional empty */
+1 -1
View File
@@ -230,7 +230,7 @@ export abstract class Pane extends Disposable implements IView {
toggleClass(this.header, 'expanded', expanded);
this.header.setAttribute('aria-expanded', String(expanded));
this.header.style.color = this.styles.headerForeground ? this.styles.headerForeground.toString() : null;
this.header.style.color = this.styles.headerForeground ? this.styles.headerForeground.toString() : '';
this.header.style.backgroundColor = this.styles.headerBackground ? this.styles.headerBackground.toString() : '';
this.header.style.borderTop = this.styles.headerBorder ? `1px solid ${this.styles.headerBorder}` : '';
this._dropBackground = this.styles.dropBackground;
+7 -1
View File
@@ -190,7 +190,13 @@ function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T,
},
getPosInSet(node) {
return node.visibleChildIndex + 1;
}
},
isChecked: options.ariaProvider && options.ariaProvider.isChecked ? (node) => {
return options.ariaProvider!.isChecked!(node.element);
} : undefined,
getRole: options.ariaProvider && options.ariaProvider.getRole ? (node) => {
return options.ariaProvider!.getRole!(node.element);
} : undefined
}
};
}
+14 -1
View File
@@ -258,7 +258,20 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
e => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T)
)
),
ariaProvider: undefined,
ariaProvider: options.ariaProvider && {
getPosInSet(el, index) {
return options.ariaProvider!.getPosInSet(el.element as T, index);
},
getSetSize(el, index, listLength) {
return options.ariaProvider!.getSetSize(el.element as T, index, listLength);
},
getRole: options.ariaProvider!.getRole ? (el) => {
return options.ariaProvider!.getRole!(el.element as T);
} : undefined,
isChecked: options.ariaProvider!.isChecked ? (e) => {
return options.ariaProvider?.isChecked!(e.element as T);
} : undefined
},
additionalScrollHeight: options.additionalScrollHeight
};
}
+1 -1
View File
@@ -668,7 +668,7 @@ export class RunOnceWorker<T> extends RunOnceScheduler {
export interface IdleDeadline {
readonly didTimeout: boolean;
timeRemaining(): DOMHighResTimeStamp;
timeRemaining(): number;
}
/**
* Execute the callback the next time the browser is idle
+1 -1
View File
@@ -6,7 +6,7 @@
import * as strings from 'vs/base/common/strings';
import * as streams from 'vs/base/common/stream';
declare var Buffer: any;
declare const Buffer: any;
const hasBuffer = (typeof Buffer !== 'undefined');
const hasTextEncoder = (typeof TextEncoder !== 'undefined');
+2 -2
View File
@@ -560,9 +560,9 @@ export function fuzzyScore(pattern: string, patternLow: string, patternStart: nu
let wordPos = wordStart;
// There will be a match, fill in tables
for (row = 1, patternPos = patternStart; patternPos < patternLen; row++ , patternPos++) {
for (row = 1, patternPos = patternStart; patternPos < patternLen; row++, patternPos++) {
for (column = 1, wordPos = wordStart; wordPos < wordLen; column++ , wordPos++) {
for (column = 1, wordPos = wordStart; wordPos < wordLen; column++, wordPos++) {
const score = _doScore(pattern, patternLow, patternPos, patternStart, word, wordLow, wordPos);
+1 -1
View File
@@ -163,7 +163,7 @@ export abstract class Disposable implements IDisposable {
/**
* Manages the lifecycle of a disposable value that may be changed.
*
* This ensures that when the the disposable value is changed, the previously held disposable is disposed of. You can
* This ensures that when the disposable value is changed, the previously held disposable is disposed of. You can
* also register a `MutableDisposable` on a `Disposable` to ensure it is automatically cleaned up.
*/
export class MutableDisposable<T extends IDisposable> implements IDisposable {
+2 -2
View File
@@ -454,8 +454,8 @@ export class ResourceMap<T> {
return this.map.delete(this.toKey(resource));
}
forEach(clb: (value: T) => void): void {
this.map.forEach(clb);
forEach(clb: (value: T, key: URI) => void): void {
this.map.forEach((value, index) => clb(value, URI.parse(index)));
}
values(): T[] {
+15 -15
View File
@@ -12,47 +12,47 @@ export namespace Schemas {
* A schema that is used for models that exist in memory
* only and that have no correspondence on a server or such.
*/
export const inMemory: string = 'inmemory';
export const inMemory = 'inmemory';
/**
* A schema that is used for setting files
*/
export const vscode: string = 'vscode';
export const vscode = 'vscode';
/**
* A schema that is used for internal private files
*/
export const internal: string = 'private';
export const internal = 'private';
/**
* A walk-through document.
*/
export const walkThrough: string = 'walkThrough';
export const walkThrough = 'walkThrough';
/**
* An embedded code snippet.
*/
export const walkThroughSnippet: string = 'walkThroughSnippet';
export const walkThroughSnippet = 'walkThroughSnippet';
export const http: string = 'http';
export const http = 'http';
export const https: string = 'https';
export const https = 'https';
export const file: string = 'file';
export const file = 'file';
export const mailto: string = 'mailto';
export const mailto = 'mailto';
export const untitled: string = 'untitled';
export const untitled = 'untitled';
export const data: string = 'data';
export const data = 'data';
export const command: string = 'command';
export const command = 'command';
export const vscodeRemote: string = 'vscode-remote';
export const vscodeRemote = 'vscode-remote';
export const vscodeRemoteResource: string = 'vscode-remote-resource';
export const vscodeRemoteResource = 'vscode-remote-resource';
export const userData: string = 'vscode-userdata';
export const userData = 'vscode-userdata';
}
class RemoteAuthoritiesImpl {
+1 -1
View File
@@ -100,7 +100,7 @@ if (typeof global === 'object') {
if (typeof define === 'function') {
// amd
define([], function () { return _factory(sharedObj); });
} else if (typeof module === "object" && typeof module.exports === "object") {
} else if (typeof module === 'object' && typeof module.exports === 'object') {
// commonjs
module.exports = _factory(sharedObj);
} else {
-9
View File
@@ -57,12 +57,3 @@ export function toUint32(v: number): number {
}
return v | 0;
}
export function toUint32Array(arr: number[]): Uint32Array {
const len = arr.length;
const r = new Uint32Array(len);
for (let i = 0; i < len; i++) {
r[i] = toUint32(arr[i]);
}
return r;
}
+1 -1
View File
@@ -390,7 +390,7 @@ interface UriState extends UriComponents {
const _pathSepMarker = isWindows ? 1 : undefined;
// tslint:disable-next-line:class-name
// eslint-disable-next-line @typescript-eslint/class-name-casing
class _URI extends URI {
_formatted: string | null = null;
+2 -2
View File
@@ -12,7 +12,7 @@ const INITIALIZE = '$initialize';
export interface IWorker extends IDisposable {
getId(): number;
postMessage(message: any, transfer: Transferable[]): void;
postMessage(message: any, transfer: ArrayBuffer[]): void;
}
export interface IWorkerCallback {
@@ -302,7 +302,7 @@ export class SimpleWorkerServer<H extends object> {
private _requestHandler: IRequestHandler | null;
private _protocol: SimpleWorkerProtocol;
constructor(postMessage: (msg: any, transfer?: Transferable[]) => void, requestHandlerFactory: IRequestHandlerFactory<H> | null) {
constructor(postMessage: (msg: any, transfer?: ArrayBuffer[]) => void, requestHandlerFactory: IRequestHandlerFactory<H> | null) {
this._requestHandlerFactory = requestHandlerFactory;
this._requestHandler = null;
this._protocol = new SimpleWorkerProtocol({
+6 -91
View File
@@ -4,8 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import * as iconv from 'iconv-lite';
import { isLinux, isMacintosh } from 'vs/base/common/platform';
import { exec } from 'child_process';
import { Readable, Writable } from 'stream';
import { VSBuffer } from 'vs/base/common/buffer';
@@ -24,9 +22,10 @@ export const UTF16be_BOM = [0xFE, 0xFF];
export const UTF16le_BOM = [0xFF, 0xFE];
export const UTF8_BOM = [0xEF, 0xBB, 0xBF];
const ZERO_BYTE_DETECTION_BUFFER_MAX_LEN = 512; // number of bytes to look at to decide about a file being binary or not
const NO_GUESS_BUFFER_MAX_LEN = 512; // when not auto guessing the encoding, small number of bytes are enough
const AUTO_GUESS_BUFFER_MAX_LEN = 512 * 8; // with auto guessing we want a lot more content to be read for guessing
const ZERO_BYTE_DETECTION_BUFFER_MAX_LEN = 512; // number of bytes to look at to decide about a file being binary or not
const NO_ENCODING_GUESS_MIN_BYTES = 512; // when not auto guessing the encoding, small number of bytes are enough
const AUTO_ENCODING_GUESS_MIN_BYTES = 512 * 8; // with auto guessing we want a lot more content to be read for guessing
const AUTO_ENCODING_GUESS_MAX_BYTES = 512 * 128; // set an upper limit for the number of bytes we pass on to jschardet
export interface IDecodeStreamOptions {
guessEncoding: boolean;
@@ -42,7 +41,7 @@ export interface IDecodeStreamResult {
export function toDecodeStream(readable: Readable, options: IDecodeStreamOptions): Promise<IDecodeStreamResult> {
if (!options.minBytesRequiredForDetection) {
options.minBytesRequiredForDetection = options.guessEncoding ? AUTO_GUESS_BUFFER_MAX_LEN : NO_GUESS_BUFFER_MAX_LEN;
options.minBytesRequiredForDetection = options.guessEncoding ? AUTO_ENCODING_GUESS_MIN_BYTES : NO_ENCODING_GUESS_MIN_BYTES;
}
return new Promise<IDecodeStreamResult>((resolve, reject) => {
@@ -212,7 +211,7 @@ const IGNORE_ENCODINGS = ['ascii', 'utf-16', 'utf-32'];
async function guessEncodingByBuffer(buffer: Buffer): Promise<string | null> {
const jschardet = await import('jschardet');
const guessed = jschardet.detect(buffer);
const guessed = jschardet.detect(buffer.slice(0, AUTO_ENCODING_GUESS_MAX_BYTES)); // ensure to limit buffer for guessing due to https://github.com/aadsm/jschardet/issues/53
if (!guessed || !guessed.encoding) {
return null;
}
@@ -353,87 +352,3 @@ export function detectEncodingFromBuffer({ buffer, bytesRead }: IReadResult, aut
return { seemsBinary, encoding };
}
// https://ss64.com/nt/chcp.html
const windowsTerminalEncodings = {
'437': 'cp437', // United States
'850': 'cp850', // Multilingual(Latin I)
'852': 'cp852', // Slavic(Latin II)
'855': 'cp855', // Cyrillic(Russian)
'857': 'cp857', // Turkish
'860': 'cp860', // Portuguese
'861': 'cp861', // Icelandic
'863': 'cp863', // Canadian - French
'865': 'cp865', // Nordic
'866': 'cp866', // Russian
'869': 'cp869', // Modern Greek
'936': 'cp936', // Simplified Chinese
'1252': 'cp1252' // West European Latin
};
export async function resolveTerminalEncoding(verbose?: boolean): Promise<string> {
let rawEncodingPromise: Promise<string>;
// Support a global environment variable to win over other mechanics
const cliEncodingEnv = process.env['VSCODE_CLI_ENCODING'];
if (cliEncodingEnv) {
if (verbose) {
console.log(`Found VSCODE_CLI_ENCODING variable: ${cliEncodingEnv}`);
}
rawEncodingPromise = Promise.resolve(cliEncodingEnv);
}
// Linux/Mac: use "locale charmap" command
else if (isLinux || isMacintosh) {
rawEncodingPromise = new Promise<string>(resolve => {
if (verbose) {
console.log('Running "locale charmap" to detect terminal encoding...');
}
exec('locale charmap', (err, stdout, stderr) => resolve(stdout));
});
}
// Windows: educated guess
else {
rawEncodingPromise = new Promise<string>(resolve => {
if (verbose) {
console.log('Running "chcp" to detect terminal encoding...');
}
exec('chcp', (err, stdout, stderr) => {
if (stdout) {
const windowsTerminalEncodingKeys = Object.keys(windowsTerminalEncodings) as Array<keyof typeof windowsTerminalEncodings>;
for (const key of windowsTerminalEncodingKeys) {
if (stdout.indexOf(key) >= 0) {
return resolve(windowsTerminalEncodings[key]);
}
}
}
return resolve(undefined);
});
});
}
const rawEncoding = await rawEncodingPromise;
if (verbose) {
console.log(`Detected raw terminal encoding: ${rawEncoding}`);
}
if (!rawEncoding || rawEncoding.toLowerCase() === 'utf-8' || rawEncoding.toLowerCase() === UTF8) {
return UTF8;
}
const iconvEncoding = toIconvLiteEncoding(rawEncoding);
if (iconv.encodingExists(iconvEncoding)) {
return iconvEncoding;
}
if (verbose) {
console.log('Unsupported terminal encoding, falling back to UTF-8.');
}
return UTF8;
}
+98
View File
@@ -0,0 +1,98 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* This code is also used by standalone cli's. Avoid adding dependencies to keep the size of the cli small.
*/
import { exec } from 'child_process';
import * as os from 'os';
const windowsTerminalEncodings = {
'437': 'cp437', // United States
'850': 'cp850', // Multilingual(Latin I)
'852': 'cp852', // Slavic(Latin II)
'855': 'cp855', // Cyrillic(Russian)
'857': 'cp857', // Turkish
'860': 'cp860', // Portuguese
'861': 'cp861', // Icelandic
'863': 'cp863', // Canadian - French
'865': 'cp865', // Nordic
'866': 'cp866', // Russian
'869': 'cp869', // Modern Greek
'936': 'cp936', // Simplified Chinese
'1252': 'cp1252' // West European Latin
};
function toIconvLiteEncoding(encodingName: string): string {
const normalizedEncodingName = encodingName.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
const mapped = JSCHARDET_TO_ICONV_ENCODINGS[normalizedEncodingName];
return mapped || normalizedEncodingName;
}
const JSCHARDET_TO_ICONV_ENCODINGS: { [name: string]: string } = {
'ibm866': 'cp866',
'big5': 'cp950'
};
const UTF8 = 'utf8';
export async function resolveTerminalEncoding(verbose?: boolean): Promise<string> {
let rawEncodingPromise: Promise<string>;
// Support a global environment variable to win over other mechanics
const cliEncodingEnv = process.env['VSCODE_CLI_ENCODING'];
if (cliEncodingEnv) {
if (verbose) {
console.log(`Found VSCODE_CLI_ENCODING variable: ${cliEncodingEnv}`);
}
rawEncodingPromise = Promise.resolve(cliEncodingEnv);
}
// Windows: educated guess
else if (os.platform() === 'win32') {
rawEncodingPromise = new Promise<string>(resolve => {
if (verbose) {
console.log('Running "chcp" to detect terminal encoding...');
}
exec('chcp', (err, stdout, stderr) => {
if (stdout) {
const windowsTerminalEncodingKeys = Object.keys(windowsTerminalEncodings) as Array<keyof typeof windowsTerminalEncodings>;
for (const key of windowsTerminalEncodingKeys) {
if (stdout.indexOf(key) >= 0) {
return resolve(windowsTerminalEncodings[key]);
}
}
}
return resolve(undefined);
});
});
}
// Linux/Mac: use "locale charmap" command
else {
rawEncodingPromise = new Promise<string>(resolve => {
if (verbose) {
console.log('Running "locale charmap" to detect terminal encoding...');
}
exec('locale charmap', (err, stdout, stderr) => resolve(stdout));
});
}
const rawEncoding = await rawEncodingPromise;
if (verbose) {
console.log(`Detected raw terminal encoding: ${rawEncoding}`);
}
if (!rawEncoding || rawEncoding.toLowerCase() === 'utf-8' || rawEncoding.toLowerCase() === UTF8) {
return UTF8;
}
return toIconvLiteEncoding(rawEncoding);
}
+1 -1
View File
@@ -187,7 +187,7 @@ const BufferPresets = {
Object: createOneByteBuffer(DataType.Object),
};
declare var Buffer: any;
declare const Buffer: any;
const hasBuffer = (typeof Buffer !== 'undefined');
function serialize(writer: IWriter, data: any): void {
@@ -406,7 +406,7 @@ export class QuickOpenWidget extends Disposable implements IModelProvider, IThem
protected applyStyles(): void {
if (this.element) {
const foreground = this.styles.foreground ? this.styles.foreground.toString() : null;
const foreground = this.styles.foreground ? this.styles.foreground.toString() : '';
const background = this.styles.background ? this.styles.background.toString() : '';
const borderColor = this.styles.borderColor ? this.styles.borderColor.toString() : '';
const widgetShadow = this.styles.widgetShadow ? this.styles.widgetShadow.toString() : '';
@@ -77,7 +77,7 @@
}
.monaco-quick-open-widget .quick-open-tree .monaco-icon-label,
.monaco-quick-open-widget .quick-open-tree .monaco-icon-label .monaco-icon-label-description-container {
.monaco-quick-open-widget .quick-open-tree .monaco-icon-label .monaco-icon-label-container > .monaco-icon-name-container {
flex: 1; /* make sure the icon label grows within the row */
}
@@ -68,9 +68,7 @@ export interface IDataSource<T> {
export interface IRenderer<T> {
getHeight(entry: T): number;
getTemplateId(entry: T): string;
// rationale: will be replaced by quickinput later
// tslint:disable-next-line: no-dom-globals
renderTemplate(templateId: string, container: HTMLElement, styles: any): any;
renderTemplate(templateId: string, container: any /* HTMLElement */, styles: any): any;
renderElement(entry: T, templateId: string, templateData: any, styles: any): void;
disposeTemplate(templateId: string, templateData: any): void;
}
@@ -137,14 +137,14 @@ suite('Storage Library', () => {
changes.clear();
// Delete is accepted
change.set('foo', undefined);
change.set('foo', undefined!);
database.fireDidChangeItemsExternal({ items: change });
ok(changes.has('foo'));
equal(storage.get('foo', null!), null);
changes.clear();
// Nothing happens if changing to same value
change.set('foo', undefined);
change.set('foo', undefined!);
database.fireDidChangeItemsExternal({ items: change });
equal(changes.size, 0);
+1
View File
@@ -136,6 +136,7 @@ suite('Event', function () {
let a = new Emitter<undefined>();
let hit = false;
a.event(function () {
// eslint-disable-next-line no-throw-literal
throw 9;
});
a.event(function () {
+1 -1
View File
@@ -47,7 +47,7 @@ suite('Lazy', () => {
assert.deepEqual(innerLazy.getValue(), [1, 11]);
});
test('map should should handle error values', () => {
test('map should handle error values', () => {
let outer = 0;
let inner = 10;
const outerLazy = new Lazy(() => { throw new Error(`${++outer}`); });
@@ -6,6 +6,7 @@
import * as assert from 'assert';
import * as fs from 'fs';
import * as encoding from 'vs/base/node/encoding';
import * as terminalEncoding from 'vs/base/node/terminalEncoding';
import { Readable } from 'stream';
import { getPathFromAmdModule } from 'vs/base/common/amd';
@@ -118,14 +119,14 @@ suite('Encoding', () => {
});
test('resolve terminal encoding (detect)', async function () {
const enc = await encoding.resolveTerminalEncoding();
assert.ok(encoding.encodingExists(enc));
const enc = await terminalEncoding.resolveTerminalEncoding();
assert.ok(enc.length > 0);
});
test('resolve terminal encoding (environment)', async function () {
process.env['VSCODE_CLI_ENCODING'] = 'utf16le';
const enc = await encoding.resolveTerminalEncoding();
const enc = await terminalEncoding.resolveTerminalEncoding();
assert.ok(encoding.encodingExists(enc));
assert.equal(enc, 'utf16le');
});
+1 -1
View File
@@ -28,7 +28,7 @@ suite('Keytar', () => {
try {
await keytar.deletePassword(name, 'foo');
} finally {
// tslint:disable-next-line: no-unsafe-finally
// eslint-disable-next-line no-unsafe-finally
throw err;
}
}
@@ -50,19 +50,18 @@ import { IFileService } from 'vs/platform/files/common/files';
import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider';
import { Schemas } from 'vs/base/common/network';
import { IProductService } from 'vs/platform/product/common/productService';
import { IUserDataSyncService, IUserDataSyncStoreService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserDataSyncService, IUserDataSyncStoreService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService, ISettingsSyncService, IUserDataAuthTokenService } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
import { UserDataSyncChannel, UserDataSyncUtilServiceClient } from 'vs/platform/userDataSync/common/userDataSyncIpc';
import { UserDataSyncChannel, UserDataSyncUtilServiceClient, SettingsSyncChannel, UserDataAuthTokenServiceChannel, UserDataAutoSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { LoggerService } from 'vs/platform/log/node/loggerService';
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
import { IAuthTokenService } from 'vs/platform/auth/common/auth';
import { AuthTokenService } from 'vs/platform/auth/electron-browser/authTokenService';
import { AuthTokenChannel } from 'vs/platform/auth/common/authTokenIpc';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { KeytarCredentialsService } from 'vs/platform/credentials/node/credentialsService';
import { UserDataAutoSync } from 'vs/platform/userDataSync/electron-browser/userDataAutoSync';
import { SettingsSynchroniser } from 'vs/platform/userDataSync/common/settingsSync';
import { UserDataAuthTokenService } from 'vs/platform/userDataSync/common/userDataAuthTokenService';
export interface ISharedProcessConfiguration {
readonly machineId: string;
@@ -182,10 +181,11 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService));
services.set(ICredentialsService, new SyncDescriptor(KeytarCredentialsService));
services.set(IAuthTokenService, new SyncDescriptor(AuthTokenService));
services.set(IUserDataAuthTokenService, new SyncDescriptor(UserDataAuthTokenService));
services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService));
services.set(IUserDataSyncUtilService, new UserDataSyncUtilServiceClient(server.getChannel('userDataSyncUtil', activeWindowRouter)));
services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService));
services.set(ISettingsSyncService, new SyncDescriptor(SettingsSynchroniser));
services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService));
registerConfiguration();
@@ -205,14 +205,22 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
const diagnosticsChannel = new DiagnosticsChannel(diagnosticsService);
server.registerChannel('diagnostics', diagnosticsChannel);
const authTokenService = accessor.get(IAuthTokenService);
const authTokenChannel = new AuthTokenChannel(authTokenService);
const authTokenService = accessor.get(IUserDataAuthTokenService);
const authTokenChannel = new UserDataAuthTokenServiceChannel(authTokenService);
server.registerChannel('authToken', authTokenChannel);
const settingsSyncService = accessor.get(ISettingsSyncService);
const settingsSyncChannel = new SettingsSyncChannel(settingsSyncService);
server.registerChannel('settingsSync', settingsSyncChannel);
const userDataSyncService = accessor.get(IUserDataSyncService);
const userDataSyncChannel = new UserDataSyncChannel(userDataSyncService);
server.registerChannel('userDataSync', userDataSyncChannel);
const userDataAutoSync = instantiationService2.createInstance(UserDataAutoSync);
const userDataAutoSyncChannel = new UserDataAutoSyncChannel(userDataAutoSync);
server.registerChannel('userDataAutoSync', userDataAutoSyncChannel);
// clean up deprecated extensions
(extensionManagementService as ExtensionManagementService).removeDeprecatedExtensions();
// update localizations cache
@@ -223,7 +231,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
instantiationService2.createInstance(LanguagePackCachedDataCleaner),
instantiationService2.createInstance(StorageDataCleaner),
instantiationService2.createInstance(LogsDataCleaner),
instantiationService2.createInstance(UserDataAutoSync)
userDataAutoSync
));
disposables.add(extensionManagementService as ExtensionManagementService);
});
+18 -17
View File
@@ -171,7 +171,7 @@ export class CodeApplication extends Disposable {
app.on('web-contents-created', (_event: Event, contents) => {
contents.on('will-attach-webview', (event: Event, webPreferences, params) => {
const isValidWebviewSource = (source: string): boolean => {
const isValidWebviewSource = (source: string | undefined): boolean => {
if (!source) {
return false;
}
@@ -191,11 +191,12 @@ export class CodeApplication extends Disposable {
webPreferences.nodeIntegration = false;
// Verify URLs being loaded
if (isValidWebviewSource(params.src) && isValidWebviewSource(webPreferences.preloadURL)) {
// https://github.com/electron/electron/issues/21553
if (isValidWebviewSource(params.src) && isValidWebviewSource((webPreferences as { preloadURL: string }).preloadURL)) {
return;
}
delete webPreferences.preloadUrl;
delete (webPreferences as { preloadURL: string }).preloadURL; // https://github.com/electron/electron/issues/21553
// Otherwise prevent loading
this.logService.error('webContents#web-contents-created: Prevented webview attach');
@@ -497,27 +498,27 @@ export class CodeApplication extends Disposable {
this.logService.info(`Tracing: waiting for windows to get ready...`);
let recordingStopped = false;
const stopRecording = (timeout: boolean) => {
const stopRecording = async (timeout: boolean) => {
if (recordingStopped) {
return;
}
recordingStopped = true; // only once
contentTracing.stopRecording(join(homedir(), `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`), path => {
if (!timeout) {
if (this.dialogMainService) {
this.dialogMainService.showMessageBox({
type: 'info',
message: localize('trace.message', "Successfully created trace."),
detail: localize('trace.detail', "Please create an issue and manually attach the following file:\n{0}", path),
buttons: [localize('trace.ok', "Ok")]
}, withNullAsUndefined(BrowserWindow.getFocusedWindow()));
}
} else {
this.logService.info(`Tracing: data recorded (after 30s timeout) to ${path}`);
const path = await contentTracing.stopRecording(join(homedir(), `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`));
if (!timeout) {
if (this.dialogMainService) {
this.dialogMainService.showMessageBox({
type: 'info',
message: localize('trace.message', "Successfully created trace."),
detail: localize('trace.detail', "Please create an issue and manually attach the following file:\n{0}", path),
buttons: [localize('trace.ok', "Ok")]
}, withNullAsUndefined(BrowserWindow.getFocusedWindow()));
}
});
} else {
this.logService.info(`Tracing: data recorded (after 30s timeout) to ${path}`);
}
};
// Wait up to 30s before creating the trace anyways
+9 -9
View File
@@ -8,7 +8,7 @@ import * as objects from 'vs/base/common/objects';
import * as nls from 'vs/nls';
import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment } from 'electron';
import { screen, BrowserWindow, systemPreferences, app, TouchBar, nativeImage, Rectangle, Display, TouchBarSegmentedControl, NativeImage, BrowserWindowConstructorOptions, SegmentedControlSegment, nativeTheme } from 'electron';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { ILogService } from 'vs/platform/log/common/log';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -347,9 +347,9 @@ export class CodeWindow extends Disposable implements ICodeWindow {
});
this._win.webContents.session.webRequest.onHeadersReceived(null!, (details, callback) => {
const responseHeaders = details.responseHeaders as { [key: string]: string[] };
const responseHeaders = details.responseHeaders as Record<string, (string) | (string[])>;
const contentType: string[] = (responseHeaders['content-type'] || responseHeaders['Content-Type']);
const contentType = (responseHeaders['content-type'] || responseHeaders['Content-Type']);
if (contentType && Array.isArray(contentType) && contentType.some(x => x.toLowerCase().indexOf('image/svg') >= 0)) {
return callback({ cancel: true });
}
@@ -441,7 +441,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// Inject headers when requests are incoming
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) =>
this.marketplaceHeadersPromise.then(headers => cb({ cancel: false, requestHeaders: objects.assign(details.requestHeaders, headers) as { [key: string]: string | undefined } })));
this.marketplaceHeadersPromise.then(headers => cb({ cancel: false, requestHeaders: objects.assign(details.requestHeaders, headers) as Record<string, string> })));
}
private onWindowError(error: WindowError): void {
@@ -648,7 +648,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
if (windowConfig?.autoDetectHighContrast === false) {
autoDetectHighContrast = false;
}
windowConfiguration.highContrast = isWindows && autoDetectHighContrast && systemPreferences.isInvertedColorScheme();
windowConfiguration.highContrast = isWindows && autoDetectHighContrast && nativeTheme.shouldUseInvertedColorScheme;
windowConfiguration.accessibilitySupport = app.accessibilitySupportEnabled;
// Title style related
@@ -1007,22 +1007,22 @@ export class CodeWindow extends Disposable implements ICodeWindow {
switch (visibility) {
case ('default'):
this._win.setMenuBarVisibility(!isFullscreen);
this._win.setAutoHideMenuBar(isFullscreen);
this._win.autoHideMenuBar = isFullscreen;
break;
case ('visible'):
this._win.setMenuBarVisibility(true);
this._win.setAutoHideMenuBar(false);
this._win.autoHideMenuBar = false;
break;
case ('toggle'):
this._win.setMenuBarVisibility(false);
this._win.setAutoHideMenuBar(true);
this._win.autoHideMenuBar = true;
break;
case ('hidden'):
this._win.setMenuBarVisibility(false);
this._win.setAutoHideMenuBar(false);
this._win.autoHideMenuBar = false;
break;
}
}
+32 -68
View File
@@ -14,10 +14,10 @@ import product from 'vs/platform/product/common/product';
import * as paths from 'vs/base/common/path';
import { whenDeleted, writeFileSync } from 'vs/base/node/pfs';
import { findFreePort, randomPort } from 'vs/base/node/ports';
import { resolveTerminalEncoding } from 'vs/base/node/encoding';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { ProfilingSession, Target } from 'v8-inspect-profiler';
import { isString } from 'vs/base/common/types';
import { hasStdinWithoutTty, stdinDataListener, getStdinFilePath, readFromStdin } from 'vs/platform/environment/node/stdin';
function shouldSpawnCliProcess(argv: ParsedArgs): boolean {
return !!argv['install-source']
@@ -142,91 +142,55 @@ export async function main(argv: string[]): Promise<any> {
});
}
let stdinWithoutTty: boolean = false;
try {
stdinWithoutTty = !process.stdin.isTTY; // Via https://twitter.com/MylesBorins/status/782009479382626304
} catch (error) {
// Windows workaround for https://github.com/nodejs/node/issues/11656
}
const readFromStdin = args._.some(a => a === '-');
if (readFromStdin) {
const hasReadStdinArg = args._.some(a => a === '-');
if (hasReadStdinArg) {
// remove the "-" argument when we read from stdin
args._ = args._.filter(a => a !== '-');
argv = argv.filter(a => a !== '-');
}
let stdinFilePath: string;
if (stdinWithoutTty) {
let stdinFilePath: string | undefined;
if (hasStdinWithoutTty()) {
// Read from stdin: we require a single "-" argument to be passed in order to start reading from
// stdin. We do this because there is no reliable way to find out if data is piped to stdin. Just
// checking for stdin being connected to a TTY is not enough (https://github.com/Microsoft/vscode/issues/40351)
if (args._.length === 0 && readFromStdin) {
// prepare temp file to read stdin to
stdinFilePath = paths.join(os.tmpdir(), `code-stdin-${Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 3)}.txt`);
if (args._.length === 0) {
if (hasReadStdinArg) {
stdinFilePath = getStdinFilePath();
// open tmp file for writing
let stdinFileError: Error | undefined;
let stdinFileStream: fs.WriteStream;
try {
stdinFileStream = fs.createWriteStream(stdinFilePath);
} catch (error) {
stdinFileError = error;
}
// returns a file path where stdin input is written into (write in progress).
try {
readFromStdin(stdinFilePath, !!verbose); // throws error if file can not be written
if (!stdinFileError) {
// Make sure to open tmp file
addArg(argv, stdinFilePath);
// Pipe into tmp file using terminals encoding
resolveTerminalEncoding(verbose).then(async encoding => {
const iconv = await import('iconv-lite');
const converterStream = iconv.decodeStream(encoding);
process.stdin.pipe(converterStream).pipe(stdinFileStream);
});
// Enable --wait to get all data and ignore adding this to history
addArg(argv, '--wait');
addArg(argv, '--skip-add-to-recently-opened');
args.wait = true;
// Make sure to open tmp file
addArg(argv, stdinFilePath);
// Enable --wait to get all data and ignore adding this to history
addArg(argv, '--wait');
addArg(argv, '--skip-add-to-recently-opened');
args.wait = true;
}
if (verbose) {
if (stdinFileError) {
console.error(`Failed to create file to read via stdin: ${stdinFileError.toString()}`);
} else {
console.log(`Reading from stdin via: ${stdinFilePath}`);
} catch (e) {
console.log(`Failed to create file to read via stdin: ${e.toString()}`);
stdinFilePath = undefined;
}
}
}
} else {
// If the user pipes data via stdin but forgot to add the "-" argument, help by printing a message
// if we detect that data flows into via stdin after a certain timeout.
else if (args._.length === 0) {
processCallbacks.push(child => new Promise(c => {
const dataListener = () => {
if (isWindows) {
console.log(`Run with '${product.applicationName} -' to read output from another program (e.g. 'echo Hello World | ${product.applicationName} -').`);
} else {
console.log(`Run with '${product.applicationName} -' to read from stdin (e.g. 'ps aux | grep code | ${product.applicationName} -').`);
// If the user pipes data via stdin but forgot to add the "-" argument, help by printing a message
// if we detect that data flows into via stdin after a certain timeout.
processCallbacks.push(_ => stdinDataListener(1000).then(dataReceived => {
if (dataReceived) {
if (isWindows) {
console.log(`Run with '${product.applicationName} -' to read output from another program (e.g. 'echo Hello World | ${product.applicationName} -').`);
} else {
console.log(`Run with '${product.applicationName} -' to read from stdin (e.g. 'ps aux | grep code | ${product.applicationName} -').`);
}
}
c(undefined);
};
// wait for 1s maximum...
setTimeout(() => {
process.stdin.removeListener('data', dataListener);
c(undefined);
}, 1000);
// ...but finish early if we detect data
process.stdin.once('data', dataListener);
}));
}));
}
}
}
@@ -10,7 +10,7 @@ import { RunOnceScheduler, TimeoutTimer } from 'vs/base/common/async';
import { Disposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
import { HitTestContext, IViewZoneData, MouseTarget, MouseTargetFactory, PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { IMouseTarget, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorMouseMoveMonitor, createEditorPagePosition } from 'vs/editor/browser/editorDom';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
@@ -148,7 +148,7 @@ export class MouseHandler extends ViewEventHandler {
}
// --- end event handlers
public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget | null {
public getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget | null {
const clientPos = new ClientCoordinates(clientX, clientY);
const pos = clientPos.toPageCoordinates();
const editorPos = createEditorPagePosition(this.viewHelper.viewDomNode);
@@ -160,7 +160,7 @@ export class MouseHandler extends ViewEventHandler {
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), editorPos, pos, null);
}
protected _createMouseTarget(e: EditorMouseEvent, testEventTarget: boolean): editorBrowser.IMouseTarget {
protected _createMouseTarget(e: EditorMouseEvent, testEventTarget: boolean): IMouseTarget {
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), e.editorPos, e.pos, testEventTarget ? e.target : null);
}
@@ -210,12 +210,12 @@ export class MouseHandler extends ViewEventHandler {
public _onMouseDown(e: EditorMouseEvent): void {
const t = this._createMouseTarget(e, true);
const targetIsContent = (t.type === editorBrowser.MouseTargetType.CONTENT_TEXT || t.type === editorBrowser.MouseTargetType.CONTENT_EMPTY);
const targetIsGutter = (t.type === editorBrowser.MouseTargetType.GUTTER_GLYPH_MARGIN || t.type === editorBrowser.MouseTargetType.GUTTER_LINE_NUMBERS || t.type === editorBrowser.MouseTargetType.GUTTER_LINE_DECORATIONS);
const targetIsLineNumbers = (t.type === editorBrowser.MouseTargetType.GUTTER_LINE_NUMBERS);
const targetIsContent = (t.type === MouseTargetType.CONTENT_TEXT || t.type === MouseTargetType.CONTENT_EMPTY);
const targetIsGutter = (t.type === MouseTargetType.GUTTER_GLYPH_MARGIN || t.type === MouseTargetType.GUTTER_LINE_NUMBERS || t.type === MouseTargetType.GUTTER_LINE_DECORATIONS);
const targetIsLineNumbers = (t.type === MouseTargetType.GUTTER_LINE_NUMBERS);
const selectOnLineNumbers = this._context.configuration.options.get(EditorOption.selectOnLineNumbers);
const targetIsViewZone = (t.type === editorBrowser.MouseTargetType.CONTENT_VIEW_ZONE || t.type === editorBrowser.MouseTargetType.GUTTER_VIEW_ZONE);
const targetIsWidget = (t.type === editorBrowser.MouseTargetType.CONTENT_WIDGET);
const targetIsViewZone = (t.type === MouseTargetType.CONTENT_VIEW_ZONE || t.type === MouseTargetType.GUTTER_VIEW_ZONE);
const targetIsWidget = (t.type === MouseTargetType.CONTENT_WIDGET);
let shouldHandle = e.leftButton || e.middleButton;
if (platform.isMacintosh && e.leftButton && e.ctrlKey) {
@@ -269,7 +269,7 @@ class MouseDownOperation extends Disposable {
private readonly _context: ViewContext;
private readonly _viewController: ViewController;
private readonly _viewHelper: IPointerHandlerHelper;
private readonly _createMouseTarget: (e: EditorMouseEvent, testEventTarget: boolean) => editorBrowser.IMouseTarget;
private readonly _createMouseTarget: (e: EditorMouseEvent, testEventTarget: boolean) => IMouseTarget;
private readonly _getMouseColumn: (e: EditorMouseEvent) => number;
private readonly _mouseMoveMonitor: GlobalEditorMouseMoveMonitor;
@@ -284,7 +284,7 @@ class MouseDownOperation extends Disposable {
context: ViewContext,
viewController: ViewController,
viewHelper: IPointerHandlerHelper,
createMouseTarget: (e: EditorMouseEvent, testEventTarget: boolean) => editorBrowser.IMouseTarget,
createMouseTarget: (e: EditorMouseEvent, testEventTarget: boolean) => IMouseTarget,
getMouseColumn: (e: EditorMouseEvent) => number
) {
super();
@@ -331,10 +331,10 @@ class MouseDownOperation extends Disposable {
}
}
public start(targetType: editorBrowser.MouseTargetType, e: EditorMouseEvent): void {
public start(targetType: MouseTargetType, e: EditorMouseEvent): void {
this._lastMouseEvent = e;
this._mouseState.setStartedOnLineNumbers(targetType === editorBrowser.MouseTargetType.GUTTER_LINE_NUMBERS);
this._mouseState.setStartedOnLineNumbers(targetType === MouseTargetType.GUTTER_LINE_NUMBERS);
this._mouseState.setStartButtons(e);
this._mouseState.setModifiers(e);
const position = this._findMousePosition(e, true);
@@ -356,13 +356,14 @@ class MouseDownOperation extends Disposable {
&& e.detail < 2 // only single click on a selection can work
&& !this._isActive // the mouse is not down yet
&& !this._currentSelection.isEmpty() // we don't drag single cursor
&& (position.type === editorBrowser.MouseTargetType.CONTENT_TEXT) // single click on text
&& (position.type === MouseTargetType.CONTENT_TEXT) // single click on text
&& position.position && this._currentSelection.containsPosition(position.position) // single click on a selection
) {
this._mouseState.isDragAndDrop = true;
this._isActive = true;
this._mouseMoveMonitor.startMonitoring(
e.buttons,
createMouseMoveEventMerger(null),
(e) => this._onMouseDownThenMove(e),
() => {
@@ -386,6 +387,7 @@ class MouseDownOperation extends Disposable {
if (!this._isActive) {
this._isActive = true;
this._mouseMoveMonitor.startMonitoring(
e.buttons,
createMouseMoveEventMerger(null),
(e) => this._onMouseDownThenMove(e),
() => this._stop()
@@ -436,12 +438,12 @@ class MouseDownOperation extends Disposable {
if (viewZoneData) {
const newPosition = this._helpPositionJumpOverViewZone(viewZoneData);
if (newPosition) {
return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, newPosition);
return new MouseTarget(null, MouseTargetType.OUTSIDE_EDITOR, mouseColumn, newPosition);
}
}
const aboveLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset);
return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(aboveLineNumber, 1));
return new MouseTarget(null, MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(aboveLineNumber, 1));
}
if (e.posy > editorContent.y + editorContent.height) {
@@ -450,22 +452,22 @@ class MouseDownOperation extends Disposable {
if (viewZoneData) {
const newPosition = this._helpPositionJumpOverViewZone(viewZoneData);
if (newPosition) {
return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, newPosition);
return new MouseTarget(null, MouseTargetType.OUTSIDE_EDITOR, mouseColumn, newPosition);
}
}
const belowLineNumber = viewLayout.getLineNumberAtVerticalOffset(verticalOffset);
return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(belowLineNumber, model.getLineMaxColumn(belowLineNumber)));
return new MouseTarget(null, MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(belowLineNumber, model.getLineMaxColumn(belowLineNumber)));
}
const possibleLineNumber = viewLayout.getLineNumberAtVerticalOffset(viewLayout.getCurrentScrollTop() + (e.posy - editorContent.y));
if (e.posx < editorContent.x) {
return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(possibleLineNumber, 1));
return new MouseTarget(null, MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(possibleLineNumber, 1));
}
if (e.posx > editorContent.x + editorContent.width) {
return new MouseTarget(null, editorBrowser.MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(possibleLineNumber, model.getLineMaxColumn(possibleLineNumber)));
return new MouseTarget(null, MouseTargetType.OUTSIDE_EDITOR, mouseColumn, new Position(possibleLineNumber, model.getLineMaxColumn(possibleLineNumber)));
}
return null;
@@ -483,7 +485,7 @@ class MouseDownOperation extends Disposable {
return null;
}
if (t.type === editorBrowser.MouseTargetType.CONTENT_VIEW_ZONE || t.type === editorBrowser.MouseTargetType.GUTTER_VIEW_ZONE) {
if (t.type === MouseTargetType.CONTENT_VIEW_ZONE || t.type === MouseTargetType.GUTTER_VIEW_ZONE) {
const newPosition = this._helpPositionJumpOverViewZone(<IViewZoneData>t.detail);
if (newPosition) {
return new MouseTarget(t.element, t.type, t.mouseColumn, newPosition, null, t.detail);
@@ -79,7 +79,7 @@ interface IETextRange {
setEndPoint(how: string, SourceRange: IETextRange): void;
}
declare var IETextRange: {
declare const IETextRange: {
prototype: IETextRange;
new(): IETextRange;
};
@@ -29,6 +29,7 @@ import { RenderingContext, RestrictedRenderingContext, HorizontalPosition } from
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
import { IEditorAriaOptions } from 'vs/editor/browser/editorBrowser';
export interface ITextAreaHandlerHelper {
visibleRangeForPositionRelativeToEditor(lineNumber: number, column: number): HorizontalPosition | null;
@@ -102,7 +103,7 @@ export class TextAreaHandler extends ViewPart {
this._accessibilityPageSize = options.get(EditorOption.accessibilityPageSize);
this._contentLeft = layoutInfo.contentLeft;
this._contentWidth = layoutInfo.contentWidth;
this._contentHeight = layoutInfo.contentHeight;
this._contentHeight = layoutInfo.height;
this._fontInfo = options.get(EditorOption.fontInfo);
this._lineHeight = options.get(EditorOption.lineHeight);
this._emptySelectionClipboard = options.get(EditorOption.emptySelectionClipboard);
@@ -353,7 +354,7 @@ export class TextAreaHandler extends ViewPart {
this._accessibilityPageSize = options.get(EditorOption.accessibilityPageSize);
this._contentLeft = layoutInfo.contentLeft;
this._contentWidth = layoutInfo.contentWidth;
this._contentHeight = layoutInfo.contentHeight;
this._contentHeight = layoutInfo.height;
this._fontInfo = options.get(EditorOption.fontInfo);
this._lineHeight = options.get(EditorOption.lineHeight);
this._emptySelectionClipboard = options.get(EditorOption.emptySelectionClipboard);
@@ -424,6 +425,18 @@ export class TextAreaHandler extends ViewPart {
return this._lastRenderPosition;
}
public setAriaOptions(options: IEditorAriaOptions): void {
if (options.activeDescendant) {
this.textArea.setAttribute('aria-haspopup', 'true');
this.textArea.setAttribute('aria-autocomplete', 'list');
this.textArea.setAttribute('aria-activedescendant', options.activeDescendant);
} else {
this.textArea.setAttribute('aria-haspopup', 'false');
this.textArea.setAttribute('aria-autocomplete', 'both');
this.textArea.removeAttribute('aria-activedescendant');
}
}
// --- end view API
private _primaryCursorPosition: Position = new Position(1, 1);
+31 -2
View File
@@ -319,6 +319,14 @@ export interface IOverviewRuler {
setLayout(position: OverviewRulerPosition): void;
}
/**
* Editor aria options.
* @internal
*/
export interface IEditorAriaOptions {
activeDescendant: string | undefined;
}
/**
* A rich code editor.
*/
@@ -482,6 +490,11 @@ export interface ICodeEditor extends editorCommon.IEditor {
* @event
*/
onDidLayoutChange(listener: (e: EditorLayoutInfo) => void): IDisposable;
/**
* An event emitted when the content width or content height in the editor has changed.
* @event
*/
onDidContentSizeChange(listener: (e: editorCommon.IContentSizeChangedEvent) => void): IDisposable;
/**
* An event emitted when the scroll in the editor has changed.
* @event
@@ -532,12 +545,12 @@ export interface ICodeEditor extends editorCommon.IEditor {
setModel(model: ITextModel | null): void;
/**
* @internal
* Gets all the editor computed options.
*/
getOptions(): IComputedEditorOptions;
/**
* @internal
* Gets a specific editor option.
*/
getOption<T extends EditorOption>(id: T): FindComputedEditorOptionValueById<T>;
@@ -558,6 +571,11 @@ export interface ICodeEditor extends editorCommon.IEditor {
*/
setValue(newValue: string): void;
/**
* Get the width of the editor's content.
* This is information that is "erased" when computing `scrollWidth = Math.max(contentWidth, width)`
*/
getContentWidth(): number;
/**
* Get the scrollWidth of the editor's viewport.
*/
@@ -567,6 +585,11 @@ export interface ICodeEditor extends editorCommon.IEditor {
*/
getScrollLeft(): number;
/**
* Get the height of the editor's content.
* This is information that is "erased" when computing `scrollHeight = Math.max(contentHeight, height)`
*/
getContentHeight(): number;
/**
* Get the scrollHeight of the editor's viewport.
*/
@@ -689,6 +712,12 @@ export interface ICodeEditor extends editorCommon.IEditor {
*/
setHiddenAreas(ranges: IRange[]): void;
/**
* Sets the editor aria options, primarily the active descendent.
* @internal
*/
setAriaOptions(options: IEditorAriaOptions): void;
/**
* @internal
*/
+3 -3
View File
@@ -172,7 +172,7 @@ export class EditorPointerEventFactory {
export class GlobalEditorMouseMoveMonitor extends Disposable {
private readonly _editorViewDomNode: HTMLElement;
protected readonly _globalMouseMoveMonitor: GlobalMouseMoveMonitor<EditorMouseEvent>;
private readonly _globalMouseMoveMonitor: GlobalMouseMoveMonitor<EditorMouseEvent>;
private _keydownListener: IDisposable | null;
constructor(editorViewDomNode: HTMLElement) {
@@ -182,7 +182,7 @@ export class GlobalEditorMouseMoveMonitor extends Disposable {
this._keydownListener = null;
}
public startMonitoring(merger: EditorMouseEventMerger, mouseMoveCallback: (e: EditorMouseEvent) => void, onStopCallback: () => void): void {
public startMonitoring(initialButtons: number, merger: EditorMouseEventMerger, mouseMoveCallback: (e: EditorMouseEvent) => void, onStopCallback: () => void): void {
// Add a <<capture>> keydown event listener that will cancel the monitoring
// if something other than a modifier key is pressed
@@ -199,7 +199,7 @@ export class GlobalEditorMouseMoveMonitor extends Disposable {
return merger(lastEvent, new EditorMouseEvent(currentEvent, this._editorViewDomNode));
};
this._globalMouseMoveMonitor.startMonitoring(myMerger, mouseMoveCallback, () => {
this._globalMouseMoveMonitor.startMonitoring(initialButtons, myMerger, mouseMoveCallback, () => {
this._keydownListener!.dispose();
onStopCallback();
});
@@ -7,22 +7,28 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { WorkspaceEdit } from 'vs/editor/common/modes';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress';
import { IDisposable } from 'vs/base/common/lifecycle';
export const IBulkEditService = createDecorator<IBulkEditService>('IWorkspaceEditService');
export interface IBulkEditOptions {
editor?: ICodeEditor;
progress?: IProgress<IProgressStep>;
showPreview?: boolean;
label?: string;
}
export interface IBulkEditResult {
ariaSummary: string;
}
export type IBulkEditPreviewHandler = (edit: WorkspaceEdit, options?: IBulkEditOptions) => Promise<WorkspaceEdit>;
export interface IBulkEditService {
_serviceBrand: undefined;
setPreviewHandler(handler: IBulkEditPreviewHandler): IDisposable;
apply(edit: WorkspaceEdit, options?: IBulkEditOptions): Promise<IBulkEditResult>;
}
@@ -0,0 +1,287 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILineBreaksComputerFactory, LineBreakData, ILineBreaksComputer } from 'vs/editor/common/viewModel/splitLinesCollection';
import { WrappingIndent } from 'vs/editor/common/config/editorOptions';
import { FontInfo } from 'vs/editor/common/config/fontInfo';
import { createStringBuilder, IStringBuilder } from 'vs/editor/common/core/stringBuilder';
import { CharCode } from 'vs/base/common/charCode';
import * as strings from 'vs/base/common/strings';
import { Configuration } from 'vs/editor/browser/config/configuration';
export class DOMLineBreaksComputerFactory implements ILineBreaksComputerFactory {
public static create(): DOMLineBreaksComputerFactory {
return new DOMLineBreaksComputerFactory();
}
constructor() {
}
public createLineBreaksComputer(fontInfo: FontInfo, tabSize: number, wrappingColumn: number, wrappingIndent: WrappingIndent): ILineBreaksComputer {
tabSize = tabSize | 0; //@perf
wrappingColumn = +wrappingColumn; //@perf
let requests: string[] = [];
return {
addRequest: (lineText: string, previousLineBreakData: LineBreakData | null) => {
requests.push(lineText);
},
finalize: () => {
return createLineBreaks(requests, fontInfo, tabSize, wrappingColumn, wrappingIndent);
}
};
}
}
function createLineBreaks(requests: string[], fontInfo: FontInfo, tabSize: number, firstLineBreakColumn: number, wrappingIndent: WrappingIndent): (LineBreakData | null)[] {
if (firstLineBreakColumn === -1) {
const result: null[] = [];
for (let i = 0, len = requests.length; i < len; i++) {
result[i] = null;
}
return result;
}
const overallWidth = Math.round(firstLineBreakColumn * fontInfo.typicalHalfwidthCharacterWidth);
// Cannot respect WrappingIndent.Indent and WrappingIndent.DeepIndent because that would require
// two dom layouts, in order to first set the width of the first line, and then set the width of the wrapped lines
if (wrappingIndent === WrappingIndent.Indent || wrappingIndent === WrappingIndent.DeepIndent) {
wrappingIndent = WrappingIndent.Same;
}
const containerDomNode = document.createElement('div');
Configuration.applyFontInfoSlow(containerDomNode, fontInfo);
const sb = createStringBuilder(10000);
const firstNonWhitespaceIndices: number[] = [];
const wrappedTextIndentLengths: number[] = [];
const renderLineContents: string[] = [];
const allCharOffsets: number[][] = [];
const allVisibleColumns: number[][] = [];
for (let i = 0; i < requests.length; i++) {
const lineContent = requests[i];
let firstNonWhitespaceIndex = 0;
let wrappedTextIndentLength = 0;
let width = overallWidth;
if (wrappingIndent !== WrappingIndent.None) {
firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent);
if (firstNonWhitespaceIndex === -1) {
// all whitespace line
firstNonWhitespaceIndex = 0;
} else {
// Track existing indent
for (let i = 0; i < firstNonWhitespaceIndex; i++) {
const charWidth = (
lineContent.charCodeAt(i) === CharCode.Tab
? (tabSize - (wrappedTextIndentLength % tabSize))
: 1
);
wrappedTextIndentLength += charWidth;
}
const indentWidth = Math.ceil(fontInfo.spaceWidth * wrappedTextIndentLength);
// Force sticking to beginning of line if no character would fit except for the indentation
if (indentWidth + fontInfo.typicalFullwidthCharacterWidth > overallWidth) {
firstNonWhitespaceIndex = 0;
wrappedTextIndentLength = 0;
} else {
width = overallWidth - indentWidth;
}
}
}
const renderLineContent = lineContent.substr(firstNonWhitespaceIndex);
const tmp = renderLine(renderLineContent, wrappedTextIndentLength, tabSize, width, sb);
firstNonWhitespaceIndices[i] = firstNonWhitespaceIndex;
wrappedTextIndentLengths[i] = wrappedTextIndentLength;
renderLineContents[i] = renderLineContent;
allCharOffsets[i] = tmp[0];
allVisibleColumns[i] = tmp[1];
}
containerDomNode.innerHTML = sb.build();
containerDomNode.style.position = 'absolute';
containerDomNode.style.top = '10000';
document.body.appendChild(containerDomNode);
let range = document.createRange();
const lineDomNodes = Array.prototype.slice.call(containerDomNode.children, 0);
let result: (LineBreakData | null)[] = [];
for (let i = 0; i < requests.length; i++) {
const lineDomNode = lineDomNodes[i];
const breakOffsets: number[] | null = readLineBreaks(range, lineDomNode, renderLineContents[i], allCharOffsets[i]);
if (breakOffsets === null) {
result[i] = null;
continue;
}
const firstNonWhitespaceIndex = firstNonWhitespaceIndices[i];
const wrappedTextIndentLength = wrappedTextIndentLengths[i];
const visibleColumns = allVisibleColumns[i];
const breakOffsetsVisibleColumn: number[] = [];
for (let j = 0, len = breakOffsets.length; j < len; j++) {
breakOffsetsVisibleColumn[j] = visibleColumns[breakOffsets[j]];
}
if (firstNonWhitespaceIndex !== 0) {
// All break offsets are relative to the renderLineContent, make them absolute again
for (let j = 0, len = breakOffsets.length; j < len; j++) {
breakOffsets[j] += firstNonWhitespaceIndex;
}
}
result[i] = new LineBreakData(breakOffsets, breakOffsetsVisibleColumn, wrappedTextIndentLength);
}
document.body.removeChild(containerDomNode);
return result;
}
function renderLine(lineContent: string, initialVisibleColumn: number, tabSize: number, width: number, sb: IStringBuilder): [number[], number[]] {
sb.appendASCIIString('<div style="width:');
sb.appendASCIIString(String(width));
sb.appendASCIIString('px;">');
// if (containsRTL) {
// sb.appendASCIIString('" dir="ltr');
// }
const len = lineContent.length;
let visibleColumn = initialVisibleColumn;
let charOffset = 0;
let charOffsets: number[] = [];
let visibleColumns: number[] = [];
let nextCharCode = (0 < len ? lineContent.charCodeAt(0) : CharCode.Null);
for (let charIndex = 0; charIndex < len; charIndex++) {
charOffsets[charIndex] = charOffset;
visibleColumns[charIndex] = visibleColumn;
const charCode = nextCharCode;
nextCharCode = (charIndex + 1 < len ? lineContent.charCodeAt(charIndex + 1) : CharCode.Null);
let producedCharacters = 1;
let charWidth = 1;
switch (charCode) {
case CharCode.Tab:
producedCharacters = (tabSize - (visibleColumn % tabSize));
charWidth = producedCharacters;
for (let space = 1; space <= producedCharacters; space++) {
if (space < producedCharacters) {
sb.write1(0xA0); // &nbsp;
} else {
sb.appendASCII(CharCode.Space);
}
}
break;
case CharCode.Space:
if (nextCharCode === CharCode.Space) {
sb.write1(0xA0); // &nbsp;
} else {
sb.appendASCII(CharCode.Space);
}
break;
case CharCode.LessThan:
sb.appendASCIIString('&lt;');
break;
case CharCode.GreaterThan:
sb.appendASCIIString('&gt;');
break;
case CharCode.Ampersand:
sb.appendASCIIString('&amp;');
break;
case CharCode.Null:
sb.appendASCIIString('&#00;');
break;
case CharCode.UTF8_BOM:
case CharCode.LINE_SEPARATOR_2028:
sb.write1(0xFFFD);
break;
default:
if (strings.isFullWidthCharacter(charCode)) {
charWidth++;
}
// if (renderControlCharacters && charCode < 32) {
// sb.write1(9216 + charCode);
// } else {
sb.write1(charCode);
// }
}
charOffset += producedCharacters;
visibleColumn += charWidth;
}
charOffsets[lineContent.length] = charOffset;
visibleColumns[lineContent.length] = visibleColumn;
sb.appendASCIIString('</div>');
return [charOffsets, visibleColumns];
}
function readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent: string, charOffsets: number[]): number[] | null {
if (lineContent.length <= 1) {
return null;
}
const textContentNode = lineDomNode.firstChild!;
const breakOffsets: number[] = [];
discoverBreaks(range, textContentNode, charOffsets, 0, null, lineContent.length - 1, null, breakOffsets);
if (breakOffsets.length === 0) {
return null;
}
breakOffsets.push(lineContent.length);
return breakOffsets;
}
type MaybeRects = ClientRectList | DOMRectList | null;
function discoverBreaks(range: Range, textContentNode: Node, charOffsets: number[], low: number, lowRects: MaybeRects, high: number, highRects: MaybeRects, result: number[]): void {
if (low === high) {
return;
}
lowRects = lowRects || readClientRect(range, textContentNode, charOffsets[low], charOffsets[low + 1]);
highRects = highRects || readClientRect(range, textContentNode, charOffsets[high], charOffsets[high + 1]);
if (Math.abs(lowRects[0].top - highRects[0].top) <= 0.1) {
// same line
return;
}
// there is at least one line break between these two offsets
if (low + 1 === high) {
// the two characters are adjacent, so the line break must be exactly between them
result.push(high);
return;
}
const mid = low + ((high - low) / 2) | 0;
const midRects = readClientRect(range, textContentNode, charOffsets[mid], charOffsets[mid + 1]);
discoverBreaks(range, textContentNode, charOffsets, low, lowRects, mid, midRects, result);
discoverBreaks(range, textContentNode, charOffsets, mid, midRects, high, highRects, result);
}
function readClientRect(range: Range, textContentNode: Node, startOffset: number, endOffset: number): ClientRectList | DOMRectList {
range.setStart(textContentNode, startOffset);
range.setEnd(textContentNode, endOffset);
return range.getClientRects();
}
+9 -2
View File
@@ -11,7 +11,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { IPointerHandlerHelper } from 'vs/editor/browser/controller/mouseHandler';
import { PointerHandler } from 'vs/editor/browser/controller/pointerHandler';
import { ITextAreaHandlerHelper, TextAreaHandler } from 'vs/editor/browser/controller/textAreaHandler';
import { IContentWidget, IContentWidgetPosition, IOverlayWidget, IOverlayWidgetPosition, IMouseTarget, IViewZoneChangeAccessor } from 'vs/editor/browser/editorBrowser';
import { IContentWidget, IContentWidgetPosition, IOverlayWidget, IOverlayWidgetPosition, IMouseTarget, IViewZoneChangeAccessor, IEditorAriaOptions } from 'vs/editor/browser/editorBrowser';
import { ICommandDelegate, ViewController } from 'vs/editor/browser/view/viewController';
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
import { ContentViewOverlays, MarginViewOverlays } from 'vs/editor/browser/view/viewOverlays';
@@ -308,6 +308,10 @@ export class View extends ViewEventHandler {
this._applyLayout();
return false;
}
public onContentSizeChanged(e: viewEvents.ViewContentSizeChangedEvent): boolean {
this.outgoingEvents.emitContentSizeChange(e);
return false;
}
public onFocusChanged(e: viewEvents.ViewFocusChangedEvent): boolean {
this.domNode.setClassName(this.getEditorClassName());
this._context.model.setHasFocus(e.isFocused);
@@ -510,6 +514,10 @@ export class View extends ViewEventHandler {
this._textAreaHandler.refreshFocusState();
}
public setAriaOptions(options: IEditorAriaOptions): void {
this._textAreaHandler.setAriaOptions(options);
}
public addContentWidget(widgetData: IContentWidgetData): void {
this.contentWidgets.addWidget(widgetData.widget);
this.layoutContentWidget(widgetData);
@@ -559,4 +567,3 @@ function safeInvokeNoArg(func: Function): any {
onUnexpectedError(e);
}
}
@@ -9,7 +9,7 @@ import { MouseTarget } from 'vs/editor/browser/controller/mouseTarget';
import { IEditorMouseEvent, IMouseTarget, IPartialEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { IScrollEvent } from 'vs/editor/common/editorCommon';
import { IScrollEvent, IContentSizeChangedEvent } from 'vs/editor/common/editorCommon';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { IViewModel, ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
@@ -20,6 +20,7 @@ export interface EventCallback<T> {
export class ViewOutgoingEvents extends Disposable {
public onDidContentSizeChange: EventCallback<IContentSizeChangedEvent> | null = null;
public onDidScroll: EventCallback<IScrollEvent> | null = null;
public onDidGainFocus: EventCallback<void> | null = null;
public onDidLoseFocus: EventCallback<void> | null = null;
@@ -41,6 +42,12 @@ export class ViewOutgoingEvents extends Disposable {
this._viewModel = viewModel;
}
public emitContentSizeChange(e: viewEvents.ViewContentSizeChangedEvent): void {
if (this.onDidContentSizeChange) {
this.onDidContentSizeChange(e);
}
}
public emitScrollChanged(e: viewEvents.ViewScrollChangedEvent): void {
if (this.onDidScroll) {
this.onDidScroll(e);
@@ -56,7 +56,7 @@ export class EditorScrollbar extends ViewPart {
fastScrollSensitivity: fastScrollSensitivity,
};
this.scrollbar = this._register(new SmoothScrollableElement(linesContent.domNode, scrollbarOptions, this._context.viewLayout.scrollable));
this.scrollbar = this._register(new SmoothScrollableElement(linesContent.domNode, scrollbarOptions, this._context.viewLayout.getScrollable()));
PartFingerprints.write(this.scrollbar.getDomNode(), PartFingerprint.ScrollableElement);
this.scrollbarDomNode = createFastDomNode(this.scrollbar.getDomNode());
@@ -113,7 +113,7 @@ export class EditorScrollbar extends ViewPart {
} else {
this.scrollbarDomNode.setWidth(layoutInfo.contentWidth);
}
this.scrollbarDomNode.setHeight(layoutInfo.contentHeight);
this.scrollbarDomNode.setHeight(layoutInfo.height);
}
public getOverviewRulerLayoutInfo(): IOverviewRulerLayoutInfo {
@@ -136,14 +136,16 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
const indent = indents[lineIndex];
let result = '';
const leftMostVisiblePosition = ctx.visibleRangeForPosition(new Position(lineNumber, 1));
let left = leftMostVisiblePosition ? leftMostVisiblePosition.left : 0;
for (let i = 1; i <= indent; i++) {
const className = (containsActiveIndentGuide && i === activeIndentLevel ? 'cigra' : 'cigr');
result += `<div class="${className}" style="left:${left}px;height:${lineHeight}px;width:${indentWidth}px"></div>`;
left += indentWidth;
if (left > scrollWidth || (this._maxIndentLeft > 0 && left > this._maxIndentLeft)) {
break;
if (indent >= 1) {
const leftMostVisiblePosition = ctx.visibleRangeForPosition(new Position(lineNumber, 1));
let left = leftMostVisiblePosition ? leftMostVisiblePosition.left : 0;
for (let i = 1; i <= indent; i++) {
const className = (containsActiveIndentGuide && i === activeIndentLevel ? 'cigra' : 'cigr');
result += `<div class="${className}" style="left:${left}px;height:${lineHeight}px;width:${indentWidth}px"></div>`;
left += indentWidth;
if (left > scrollWidth || (this._maxIndentLeft > 0 && left > this._maxIndentLeft)) {
break;
}
}
}
@@ -213,6 +213,7 @@ export class ViewLine implements IVisibleLine {
lineData.tokens,
actualInlineDecorations,
lineData.tabSize,
lineData.startVisibleColumn,
options.spaceWidth,
options.stopRenderingLineAfter,
options.renderWhitespace,
@@ -513,9 +514,16 @@ class RenderedViewLine implements IRenderedViewLine {
return 0;
}
if (this._containsForeignElements === ForeignElementType.Before) {
// We have foreign element before the (empty) line
// We have foreign elements before the (empty) line
return this.getWidth();
}
// We have foreign elements before & after the (empty) line
const readingTarget = this._getReadingTarget(domNode);
if (readingTarget.firstChild) {
return (<HTMLSpanElement>readingTarget.firstChild).offsetWidth;
} else {
return 0;
}
}
if (this._pixelOffsetCache !== null) {
@@ -555,6 +555,7 @@ export class Minimap extends ViewPart {
this._slider.toggleClassName('active', true);
this._sliderMouseMoveMonitor.startMonitoring(
e.buttons,
standardMouseMoveMerger,
(mouseMoveData: IStandardMouseMoveEventData) => {
const mouseOrthogonalDelta = Math.abs(mouseMoveData.posx - initialMouseOrthogonalPosition);
@@ -50,6 +50,8 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { withNullAsUndefined } from 'vs/base/common/types';
import { MonospaceLineBreaksComputerFactory } from 'vs/editor/common/viewModel/monospaceLineBreaksComputer';
import { DOMLineBreaksComputerFactory } from 'vs/editor/browser/view/domLineBreaksComputer';
let EDITOR_ID = 0;
@@ -193,6 +195,9 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
private readonly _onKeyDown: Emitter<IKeyboardEvent> = this._register(new Emitter<IKeyboardEvent>());
public readonly onKeyDown: Event<IKeyboardEvent> = this._onKeyDown.event;
private readonly _onDidContentSizeChange: Emitter<editorCommon.IContentSizeChangedEvent> = this._register(new Emitter<editorCommon.IContentSizeChangedEvent>());
public readonly onDidContentSizeChange: Event<editorCommon.IContentSizeChangedEvent> = this._onDidContentSizeChange.event;
private readonly _onDidScrollChange: Emitter<editorCommon.IScrollEvent> = this._register(new Emitter<editorCommon.IScrollEvent>());
public readonly onDidScrollChange: Event<editorCommon.IScrollEvent> = this._onDidScrollChange.event;
@@ -757,6 +762,13 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
this._modelData.cursor.setSelections(source, ranges);
}
public getContentWidth(): number {
if (!this._modelData) {
return -1;
}
return this._modelData.viewModel.viewLayout.getContentWidth();
}
public getScrollWidth(): number {
if (!this._modelData) {
return -1;
@@ -770,6 +782,13 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
return this._modelData.viewModel.viewLayout.getCurrentScrollLeft();
}
public getContentHeight(): number {
if (!this._modelData) {
return -1;
}
return this._modelData.viewModel.viewLayout.getContentHeight();
}
public getScrollHeight(): number {
if (!this._modelData) {
return -1;
@@ -1311,6 +1330,13 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
this._modelData.view.render(true, forceRedraw);
}
public setAriaOptions(options: editorBrowser.IEditorAriaOptions): void {
if (!this._modelData || !this._modelData.hasRealView) {
return;
}
this._modelData.view.setAriaOptions(options);
}
public applyFontInfo(target: HTMLElement): void {
Configuration.applyFontInfoSlow(target, this._configuration.options.get(EditorOption.fontInfo));
}
@@ -1329,7 +1355,14 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
model.onBeforeAttached();
const viewModel = new ViewModel(this._id, this._configuration, model, (callback) => dom.scheduleAtNextAnimationFrame(callback));
const viewModel = new ViewModel(
this._id,
this._configuration,
model,
DOMLineBreaksComputerFactory.create(),
MonospaceLineBreaksComputerFactory.create(this._configuration.options),
(callback) => dom.scheduleAtNextAnimationFrame(callback)
);
listenersToRemove.push(model.onDidChangeDecorations((e) => this._onDidChangeModelDecorations.fire(e)));
listenersToRemove.push(model.onDidChangeLanguage((e) => {
@@ -1463,6 +1496,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
}
const viewOutgoingEvents = new ViewOutgoingEvents(viewModel);
viewOutgoingEvents.onDidContentSizeChange = (e) => this._onDidContentSizeChange.fire(e);
viewOutgoingEvents.onDidScroll = (e) => this._onDidScrollChange.fire(e);
viewOutgoingEvents.onDidGainFocus = () => this._editorTextFocus.setValue(true);
viewOutgoingEvents.onDidLoseFocus = () => this._editorTextFocus.setValue(false);
@@ -1130,11 +1130,11 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
let scrollTop = this.modifiedEditor.getScrollTop();
let scrollHeight = this.modifiedEditor.getScrollHeight();
let computedAvailableSize = Math.max(0, layoutInfo.contentHeight);
let computedAvailableSize = Math.max(0, layoutInfo.height);
let computedRepresentableSize = Math.max(0, computedAvailableSize - 2 * 0);
let computedRatio = scrollHeight > 0 ? (computedRepresentableSize / scrollHeight) : 0;
let computedSliderSize = Math.max(0, Math.floor(layoutInfo.contentHeight * computedRatio));
let computedSliderSize = Math.max(0, Math.floor(layoutInfo.height * computedRatio));
let computedSliderPosition = Math.floor(scrollTop * computedRatio);
return {
@@ -1629,7 +1629,7 @@ const DECORATIONS = {
}),
lineInsertWithSign: ModelDecorationOptions.register({
className: 'line-insert',
linesDecorationsClassName: 'insert-sign',
linesDecorationsClassName: 'insert-sign codicon codicon-add',
marginClassName: 'line-insert',
isWholeLine: true
}),
@@ -1641,7 +1641,7 @@ const DECORATIONS = {
}),
lineDeleteWithSign: ModelDecorationOptions.register({
className: 'line-delete',
linesDecorationsClassName: 'delete-sign',
linesDecorationsClassName: 'delete-sign codicon codicon-remove',
marginClassName: 'line-delete',
isWholeLine: true
@@ -2100,7 +2100,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
if (this.renderIndicators) {
let index = lineNumber - lineChange.originalStartLineNumber;
marginHTML = marginHTML.concat([
`<div class="delete-sign" style="position:absolute;top:${index * lineHeight}px;width:${lineDecorationsWidth}px;height:${lineHeight}px;right:0;"></div>`
`<div class="delete-sign codicon codicon-remove" style="position:absolute;top:${index * lineHeight}px;width:${lineDecorationsWidth}px;height:${lineHeight}px;right:0;"></div>`
]);
}
}
@@ -2162,6 +2162,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
lineTokens,
actualDecorations,
tabSize,
0,
fontInfo.spaceWidth,
options.get(EditorOption.stopRenderingLineAfter),
options.get(EditorOption.renderWhitespace),
@@ -780,6 +780,7 @@ export class DiffReview extends Disposable {
lineTokens,
[],
tabSize,
0,
fontInfo.spaceWidth,
options.get(EditorOption.stopRenderingLineAfter),
options.get(EditorOption.renderWhitespace),
@@ -9,7 +9,7 @@ import { Action } from 'vs/base/common/actions';
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { Range } from 'vs/editor/common/core/range';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
@@ -57,7 +57,7 @@ export class InlineDiffMargin extends Disposable {
this._marginDomNode.style.zIndex = '10';
this._diffActions = document.createElement('div');
this._diffActions.className = 'lightbulb-glyph';
this._diffActions.className = 'codicon codicon-lightbulb lightbulb-glyph';
this._diffActions.style.position = 'absolute';
const lineHeight = editor.getOption(EditorOption.lineHeight);
const lineFeed = editor.getModel()!.getEOL();
@@ -150,8 +150,8 @@ export class InlineDiffMargin extends Disposable {
}));
this._register(editor.onMouseMove((e: editorBrowser.IEditorMouseEvent) => {
if (e.target.type === editorBrowser.MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === editorBrowser.MouseTargetType.GUTTER_VIEW_ZONE) {
this._register(editor.onMouseMove((e: IEditorMouseEvent) => {
if (e.target.type === MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === MouseTargetType.GUTTER_VIEW_ZONE) {
const viewZoneId = e.target.detail.viewZoneId;
if (viewZoneId === this._viewZoneId) {
@@ -165,12 +165,12 @@ export class InlineDiffMargin extends Disposable {
}
}));
this._register(editor.onMouseDown((e: editorBrowser.IEditorMouseEvent) => {
this._register(editor.onMouseDown((e: IEditorMouseEvent) => {
if (!e.event.rightButton) {
return;
}
if (e.target.type === editorBrowser.MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === editorBrowser.MouseTargetType.GUTTER_VIEW_ZONE) {
if (e.target.type === MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === MouseTargetType.GUTTER_VIEW_ZONE) {
const viewZoneId = e.target.detail.viewZoneId;
if (viewZoneId === this._viewZoneId) {
@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 7V8H8V14H7V8H1V7H7V1H8V7H14Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 163 B

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 7V8H8V14H7V8H1V7H7V1H8V7H14Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 163 B

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