提交 83af15cc 编写于 作者: B Benjamin Pasero

Merge branch 'master' into ben/labels

......@@ -15,6 +15,8 @@ const util = require('./lib/util');
const packageJson = require('../package.json');
const product = require('../product.json');
const rpmDependencies = require('../resources/linux/rpm/dependencies.json');
const path = require('path');
const root = path.dirname(__dirname);
const commit = util.getVersion(root);
const linuxPackageRevision = Math.floor(new Date().getTime() / 1000);
......@@ -198,7 +200,7 @@ function prepareSnapPackage(arch) {
const snapcraft = gulp.src('resources/linux/snap/snapcraft.yaml', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@VERSION@@', commit.substr(32)))
.pipe(replace('@@VERSION@@', commit.substr(0, 8)))
.pipe(rename('snap/snapcraft.yaml'));
const snapUpdate = gulp.src('resources/linux/snap/snapUpdate.sh', { base: '.' })
......
......@@ -106,9 +106,11 @@
"./vs/base/test/browser/progressBar.test.ts",
"./vs/base/test/browser/ui/contextview/contextview.test.ts",
"./vs/base/test/browser/ui/grid/grid.test.ts",
"./vs/base/test/browser/ui/grid/gridview.test.ts",
"./vs/base/test/browser/ui/grid/util.ts",
"./vs/base/test/browser/ui/list/listView.test.ts",
"./vs/base/test/browser/ui/list/rangeMap.test.ts",
"./vs/base/test/browser/ui/splitview/splitview.test.ts",
"./vs/base/test/browser/ui/scrollbar/scrollableElement.test.ts",
"./vs/base/test/browser/ui/scrollbar/scrollbarState.test.ts",
"./vs/base/test/browser/ui/tree/asyncDataTree.test.ts",
......
......@@ -281,6 +281,7 @@ export abstract class AbstractScrollableElement extends Widget {
let massagedOptions = resolveOptions(newOptions);
this._options.handleMouseWheel = massagedOptions.handleMouseWheel;
this._options.mouseWheelScrollSensitivity = massagedOptions.mouseWheelScrollSensitivity;
this._options.fastScrollSensitivity = massagedOptions.fastScrollSensitivity;
this._setListeningToMouseWheel(this._options.handleMouseWheel);
if (!this._options.lazyRender) {
......@@ -340,6 +341,12 @@ export abstract class AbstractScrollableElement extends Widget {
deltaY = 0;
}
if (e.browserEvent && e.browserEvent.altKey) {
// fastScrolling
deltaX = deltaX * this._options.fastScrollSensitivity;
deltaY = deltaY * this._options.fastScrollSensitivity;
}
const futureScrollPosition = this._scrollable.getFutureScrollPosition();
let desiredScrollPosition: INewScrollPosition = {};
......@@ -540,6 +547,7 @@ function resolveOptions(opts: ScrollableElementCreationOptions): ScrollableEleme
alwaysConsumeMouseWheel: (typeof opts.alwaysConsumeMouseWheel !== 'undefined' ? opts.alwaysConsumeMouseWheel : false),
scrollYToX: (typeof opts.scrollYToX !== 'undefined' ? opts.scrollYToX : false),
mouseWheelScrollSensitivity: (typeof opts.mouseWheelScrollSensitivity !== 'undefined' ? opts.mouseWheelScrollSensitivity : 1),
fastScrollSensitivity: (typeof opts.fastScrollSensitivity !== 'undefined' ? opts.fastScrollSensitivity : 5),
mouseWheelSmoothScroll: (typeof opts.mouseWheelSmoothScroll !== 'undefined' ? opts.mouseWheelSmoothScroll : true),
arrowSize: (typeof opts.arrowSize !== 'undefined' ? opts.arrowSize : 11),
......
......@@ -50,6 +50,11 @@ export interface ScrollableElementCreationOptions {
* Defaults to 1.
*/
mouseWheelScrollSensitivity?: number;
/**
* FastScrolling mulitplier speed when pressing `Alt`
* Defaults to 5.
*/
fastScrollSensitivity?: number;
/**
* Height for vertical arrows (top/bottom) and width for horizontal arrows (left/right).
* Defaults to 11.
......@@ -107,6 +112,7 @@ export interface ScrollableElementCreationOptions {
export interface ScrollableElementChangeOptions {
handleMouseWheel?: boolean;
mouseWheelScrollSensitivity?: number;
fastScrollSensitivity: number;
}
export interface ScrollableElementResolvedOptions {
......@@ -118,6 +124,7 @@ export interface ScrollableElementResolvedOptions {
scrollYToX: boolean;
alwaysConsumeMouseWheel: boolean;
mouseWheelScrollSensitivity: number;
fastScrollSensitivity: number;
mouseWheelSmoothScroll: boolean;
arrowSize: number;
listenOnDomNode: HTMLElement | null;
......
......@@ -514,6 +514,16 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
private setChildren(node: IAsyncDataTreeNode<TInput, T>, childrenElements: T[], recursive: boolean): void {
let nodeChildren: Map<string, IAsyncDataTreeNode<TInput, T>> | undefined;
if (this.identityProvider) {
nodeChildren = new Map();
for (const child of node.children!) {
nodeChildren.set(child.id!, child);
}
}
const children = childrenElements.map<ITreeElement<IAsyncDataTreeNode<TInput, T>>>(element => {
if (!this.identityProvider) {
return {
......@@ -527,14 +537,8 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
};
}
const nodeChildren = new Map<string, IAsyncDataTreeNode<TInput, T>>();
for (const child of node.children!) {
nodeChildren.set(child.id!, child);
}
const id = this.identityProvider.getId(element).toString();
const asyncDataTreeNode = nodeChildren.get(id);
const asyncDataTreeNode = nodeChildren!.get(id);
if (!asyncDataTreeNode) {
return {
......
......@@ -21,10 +21,6 @@ suite('Gridview', function () {
container.appendChild(gridview.element);
});
teardown(function () {
gridview = null;
});
test('empty gridview is empty', function () {
assert.deepEqual(nodesToArrays(gridview.getViews()), []);
gridview.dispose();
......
......@@ -72,13 +72,9 @@ suite('Splitview', () => {
container.style.height = `${200}px`;
});
teardown(() => {
container = null;
});
test('empty splitview has empty DOM', () => {
const splitview = new SplitView(container);
assert.equal(container.firstElementChild.firstElementChild.childElementCount, 0, 'split view should be empty');
assert.equal(container.firstElementChild!.firstElementChild!.childElementCount, 0, 'split view should be empty');
splitview.dispose();
});
......
......@@ -48,6 +48,7 @@ export class EditorScrollbar extends ViewPart {
handleMouseWheel: configScrollbarOpts.handleMouseWheel,
arrowSize: configScrollbarOpts.arrowSize,
mouseWheelScrollSensitivity: configScrollbarOpts.mouseWheelScrollSensitivity,
fastScrollSensitivity: configScrollbarOpts.fastScrollSensitivity,
};
this.scrollbar = this._register(new SmoothScrollableElement(linesContent.domNode, scrollbarOptions, this._context.viewLayout.scrollable));
......@@ -127,7 +128,8 @@ export class EditorScrollbar extends ViewPart {
const editor = this._context.configuration.editor;
let newOpts: ScrollableElementChangeOptions = {
handleMouseWheel: editor.viewInfo.scrollbar.handleMouseWheel,
mouseWheelScrollSensitivity: editor.viewInfo.scrollbar.mouseWheelScrollSensitivity
mouseWheelScrollSensitivity: editor.viewInfo.scrollbar.mouseWheelScrollSensitivity,
fastScrollSensitivity: editor.viewInfo.scrollbar.fastScrollSensitivity
};
this.scrollbar.updateOptions(newOpts);
}
......
......@@ -429,6 +429,11 @@ const editorConfiguration: IConfigurationNode = {
'default': EDITOR_DEFAULTS.viewInfo.scrollbar.mouseWheelScrollSensitivity,
'markdownDescription': nls.localize('mouseWheelScrollSensitivity', "A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.")
},
'editor.fastScrollSensitivity': {
'type': 'number',
'default': EDITOR_DEFAULTS.viewInfo.scrollbar.fastScrollSensitivity,
'markdownDescription': nls.localize('fastScrollSensitivity', "Scrolling speed mulitiplier when pressing `Alt`")
},
'editor.multiCursorModifier': {
'type': 'string',
'enum': ['ctrlCmd', 'alt'],
......
......@@ -458,6 +458,11 @@ export interface IEditorOptions {
* Defaults to 1.
*/
mouseWheelScrollSensitivity?: number;
/**
* FastScrolling mulitplier speed when pressing `Alt`
* Defaults to 5.
*/
fastScrollSensitivity?: number;
/**
* The modifier to be used to add multiple cursors with the mouse.
* Defaults to 'alt'
......@@ -875,6 +880,7 @@ export interface InternalEditorScrollbarOptions {
readonly verticalScrollbarSize: number;
readonly verticalSliderSize: number;
readonly mouseWheelScrollSensitivity: number;
readonly fastScrollSensitivity: number;
}
export interface InternalEditorMinimapOptions {
......@@ -1292,6 +1298,7 @@ export class InternalEditorOptions {
&& a.verticalScrollbarSize === b.verticalScrollbarSize
&& a.verticalSliderSize === b.verticalSliderSize
&& a.mouseWheelScrollSensitivity === b.mouseWheelScrollSensitivity
&& a.fastScrollSensitivity === b.fastScrollSensitivity
);
}
......@@ -1795,7 +1802,7 @@ export class EditorOptionsValidator {
};
}
private static _sanitizeScrollbarOpts(opts: IEditorScrollbarOptions | undefined, defaults: InternalEditorScrollbarOptions, mouseWheelScrollSensitivity: number): InternalEditorScrollbarOptions {
private static _sanitizeScrollbarOpts(opts: IEditorScrollbarOptions | undefined, defaults: InternalEditorScrollbarOptions, mouseWheelScrollSensitivity: number, fastScrollSensitivity: number): InternalEditorScrollbarOptions {
if (typeof opts !== 'object') {
return defaults;
}
......@@ -1818,7 +1825,8 @@ export class EditorOptionsValidator {
verticalSliderSize: _clampedInt(opts.verticalSliderSize, verticalScrollbarSize, 0, 1000),
handleMouseWheel: _boolean(opts.handleMouseWheel, defaults.handleMouseWheel),
mouseWheelScrollSensitivity: mouseWheelScrollSensitivity
mouseWheelScrollSensitivity: mouseWheelScrollSensitivity,
fastScrollSensitivity: fastScrollSensitivity,
};
}
......@@ -1965,7 +1973,12 @@ export class EditorOptionsValidator {
// Disallow 0, as it would prevent/block scrolling
mouseWheelScrollSensitivity = 1;
}
const scrollbar = this._sanitizeScrollbarOpts(opts.scrollbar, defaults.scrollbar, mouseWheelScrollSensitivity);
let fastScrollSensitivity = _float(opts.fastScrollSensitivity, defaults.scrollbar.fastScrollSensitivity);
if (fastScrollSensitivity <= 0) {
fastScrollSensitivity = defaults.scrollbar.fastScrollSensitivity;
}
const scrollbar = this._sanitizeScrollbarOpts(opts.scrollbar, defaults.scrollbar, mouseWheelScrollSensitivity, fastScrollSensitivity);
const minimap = this._sanitizeMinimapOpts(opts.minimap, defaults.minimap);
return {
......@@ -2592,6 +2605,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = {
verticalSliderSize: 14,
handleMouseWheel: true,
mouseWheelScrollSensitivity: 1,
fastScrollSensitivity: 5,
},
minimap: {
enabled: true,
......
......@@ -17,11 +17,15 @@ import { CancellationToken } from 'vs/base/common/cancellation';
export class NoProviderError extends Error {
static readonly Name = 'NOPRO';
static is(thing: any): thing is NoProviderError {
return thing instanceof Error && thing.name === NoProviderError._name;
}
private static readonly _name = 'NOPRO';
constructor(message?: string) {
super();
this.name = NoProviderError.Name;
this.name = NoProviderError._name;
if (message) {
this.message = message;
}
......
......@@ -9,9 +9,9 @@ import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { registerEditorAction, ServicesAccessor, EditorAction, registerEditorContribution, IActionOptions } from 'vs/editor/browser/editorExtensions';
import { OnTypeFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry } from 'vs/editor/common/modes';
import { getOnTypeFormattingEdits, getDocumentFormattingEdits, getDocumentRangeFormattingEdits, NoProviderError } from 'vs/editor/contrib/format/format';
import { registerEditorAction, ServicesAccessor, EditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { OnTypeFormattingEditProviderRegistry, DocumentRangeFormattingEditProviderRegistry, DocumentFormattingEditProviderRegistry, FormattingOptions } from 'vs/editor/common/modes';
import { getOnTypeFormattingEdits, NoProviderError } from 'vs/editor/contrib/format/format';
import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
......@@ -21,12 +21,12 @@ import { Range } from 'vs/editor/common/core/range';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { EditorState, CodeEditorStateFlag } from 'vs/editor/browser/core/editorState';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
import { ISingleEditOperation } from 'vs/editor/common/model';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { CancellationToken } from 'vs/base/common/cancellation';
import { sequence } from 'vs/base/common/async';
function alertFormattingEdits(edits: ISingleEditOperation[]): void {
......@@ -55,6 +55,98 @@ function alertFormattingEdits(edits: ISingleEditOperation[]): void {
}
}
export const enum FormatRangeType {
Full,
Selection,
}
export function formatDocumentRange(workerService: IEditorWorkerService, editor: IActiveCodeEditor, rangeOrRangeType: Range | FormatRangeType, options: FormattingOptions, token: CancellationToken): Promise<void> {
const provider = DocumentRangeFormattingEditProviderRegistry.ordered(editor.getModel()).slice(0, 1);
if (provider.length === 0) {
return Promise.reject(new NoProviderError());
}
let allEdits: ISingleEditOperation[] = [];
editor.pushUndoStop();
return sequence(provider.map(provider => {
// create a formatting task per provider. they run sequentially,
// potentially undoing the working of a previous formatter
return () => {
const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
const model = editor.getModel();
let range: Range;
if (rangeOrRangeType === FormatRangeType.Full) {
// full
range = model.getFullModelRange();
} else if (rangeOrRangeType === FormatRangeType.Selection) {
// selection or line (when empty)
range = editor.getSelection();
if (range.isEmpty()) {
range = new Range(range.startLineNumber, 1, range.endLineNumber, model.getLineMaxColumn(range.endLineNumber));
}
} else {
// as is
range = rangeOrRangeType;
}
return Promise.resolve(provider.provideDocumentRangeFormattingEdits(model, range, options, token)).then(edits => {
// break edits into smaller edits
return workerService.computeMoreMinimalEdits(editor.getModel().uri, edits);
}).then(edits => {
// make edit only when the editor didn't change while
// computing and only when there are edits
if (state.validate(editor) && isNonEmptyArray(edits)) {
FormattingEdit.execute(editor, edits);
allEdits = allEdits.concat(edits);
}
});
};
})).then(() => {
alertFormattingEdits(allEdits);
editor.pushUndoStop();
editor.focus();
editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
});
}
export function formatDocument(workerService: IEditorWorkerService, editor: IActiveCodeEditor, options: FormattingOptions, token: CancellationToken): Promise<void> {
const provider = DocumentFormattingEditProviderRegistry.ordered(editor.getModel()).slice(0);
if (provider.length === 0) {
return formatDocumentRange(workerService, editor, FormatRangeType.Full, options, token);
}
let allEdits: ISingleEditOperation[] = [];
editor.pushUndoStop();
return sequence(provider.map(provider => {
// create a formatting task per provider. they run sequentially,
// potentially undoing the working of a previous formatter
return () => {
const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
const model = editor.getModel();
return Promise.resolve(provider.provideDocumentFormattingEdits(model, options, token)).then(edits => {
// break edits into smaller edits
return workerService.computeMoreMinimalEdits(editor.getModel().uri, edits);
}).then(edits => {
// make edit only when the editor didn't change while
// computing and only when there are edits
if (state.validate(editor) && isNonEmptyArray(edits)) {
FormattingEdit.execute(editor, edits);
allEdits = allEdits.concat(edits);
}
});
};
})).then(() => {
alertFormattingEdits(allEdits);
editor.pushUndoStop();
editor.focus();
editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
});
}
class FormatOnType implements editorCommon.IEditorContribution {
private static readonly ID = 'editor.contrib.autoFormat';
......@@ -224,8 +316,7 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
let model = this.editor.getModel();
// no support
let [support] = DocumentRangeFormattingEditProviderRegistry.ordered(model);
if (!support || !support.provideDocumentRangeFormattingEdits) {
if (!DocumentRangeFormattingEditProviderRegistry.has(model)) {
return;
}
......@@ -245,19 +336,7 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
const model = this.editor.getModel();
const { tabSize, insertSpaces } = model.getOptions();
const state = new EditorState(this.editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
getDocumentRangeFormattingEdits(model, range, { tabSize, insertSpaces }, CancellationToken.None).then(edits => {
return this.workerService.computeMoreMinimalEdits(model.uri, edits);
}).then(edits => {
if (!state.validate(this.editor)) {
return;
}
if (isNonEmptyArray(edits)) {
FormattingEdit.execute(this.editor, edits);
alertFormattingEdits(edits);
}
});
formatDocumentRange(this.workerService, this.editor, range, { tabSize, insertSpaces }, CancellationToken.None);
}
public getId(): string {
......@@ -270,53 +349,7 @@ class FormatOnPaste implements editorCommon.IEditorContribution {
}
}
export abstract class AbstractFormatAction extends EditorAction {
public run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> {
if (!editor.hasModel()) {
return Promise.resolve(void 0);
}
const workerService = accessor.get(IEditorWorkerService);
const notificationService = accessor.get(INotificationService);
const formattingPromise = this._getFormattingEdits(editor, CancellationToken.None);
if (!formattingPromise) {
return Promise.resolve(void 0);
}
// Capture the state of the editor
const state = new EditorState(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Position);
// Receive formatted value from worker
return formattingPromise.then(edits => workerService.computeMoreMinimalEdits(editor.getModel().uri, edits)).then(edits => {
if (!state.validate(editor)) {
return;
}
if (isNonEmptyArray(edits)) {
FormattingEdit.execute(editor, edits);
alertFormattingEdits(edits);
editor.focus();
editor.revealPositionInCenterIfOutsideViewport(editor.getPosition(), editorCommon.ScrollType.Immediate);
}
}, err => {
if (err instanceof Error && err.name === NoProviderError.Name) {
this._notifyNoProviderError(notificationService, editor.getModel().getLanguageIdentifier().language);
} else {
throw err;
}
});
}
protected abstract _getFormattingEdits(editor: ICodeEditor, token: CancellationToken): Promise<ISingleEditOperation[] | null | undefined> | undefined;
protected _notifyNoProviderError(notificationService: INotificationService, language: string): void {
notificationService.info(nls.localize('no.provider', "There is no formatter for '{0}'-files installed.", language));
}
}
export class FormatDocumentAction extends AbstractFormatAction {
export class FormatDocumentAction extends EditorAction {
constructor() {
super({
......@@ -339,21 +372,22 @@ export class FormatDocumentAction extends AbstractFormatAction {
});
}
protected _getFormattingEdits(editor: ICodeEditor, token: CancellationToken): Promise<ISingleEditOperation[] | null | undefined> | undefined {
run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> | void {
if (!editor.hasModel()) {
return undefined;
return;
}
const model = editor.getModel();
const { tabSize, insertSpaces } = model.getOptions();
return getDocumentFormattingEdits(model, { tabSize, insertSpaces }, token);
}
protected _notifyNoProviderError(notificationService: INotificationService, language: string): void {
notificationService.info(nls.localize('no.documentprovider', "There is no document formatter for '{0}'-files installed.", language));
const notificationService = accessor.get(INotificationService);
const workerService = accessor.get(IEditorWorkerService);
const { tabSize, insertSpaces } = editor.getModel().getOptions();
return formatDocument(workerService, editor, { tabSize, insertSpaces }, CancellationToken.None).catch(err => {
if (NoProviderError.is(err)) {
notificationService.info(nls.localize('no.documentprovider', "There is no document formatter for '{0}'-files installed.", editor.getModel().getLanguageIdentifier().language));
}
});
}
}
export class FormatSelectionAction extends AbstractFormatAction {
export class FormatSelectionAction extends EditorAction {
constructor() {
super({
......@@ -374,24 +408,18 @@ export class FormatSelectionAction extends AbstractFormatAction {
});
}
protected _getFormattingEdits(editor: ICodeEditor, token: CancellationToken): Promise<ISingleEditOperation[] | null | undefined> | undefined {
run(accessor: ServicesAccessor, editor: ICodeEditor): Promise<void> | void {
if (!editor.hasModel()) {
return undefined;
}
const model = editor.getModel();
let selection = editor.getSelection();
if (selection.isEmpty()) {
const maxColumn = model.getLineMaxColumn(selection.startLineNumber);
selection = selection.setStartPosition(selection.startLineNumber, 1);
selection = selection.setEndPosition(selection.endLineNumber, maxColumn);
return;
}
const { tabSize, insertSpaces } = model.getOptions();
return getDocumentRangeFormattingEdits(model, selection, { tabSize, insertSpaces }, token);
}
protected _notifyNoProviderError(notificationService: INotificationService, language: string): void {
notificationService.info(nls.localize('no.selectionprovider', "There is no selection formatter for '{0}'-files installed.", language));
const notificationService = accessor.get(INotificationService);
const workerService = accessor.get(IEditorWorkerService);
const { tabSize, insertSpaces } = editor.getModel().getOptions();
return formatDocumentRange(workerService, editor, FormatRangeType.Selection, { tabSize, insertSpaces }, CancellationToken.None).catch(err => {
if (NoProviderError.is(err)) {
notificationService.info(nls.localize('no.selectionprovider', "There is no selection formatter for '{0}'-files installed.", editor.getModel().getLanguageIdentifier().language));
}
});
}
}
......@@ -404,25 +432,15 @@ registerEditorAction(FormatSelectionAction);
// and we keep it here such that existing keybinding configurations etc will still work
CommandsRegistry.registerCommand('editor.action.format', accessor => {
const editor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
if (editor) {
return new class extends AbstractFormatAction {
constructor() {
super({} as IActionOptions);
}
_getFormattingEdits(editor: ICodeEditor, token: CancellationToken): Promise<ISingleEditOperation[] | null | undefined> | undefined {
if (!editor.hasModel()) {
return undefined;
}
const model = editor.getModel();
const editorSelection = editor.getSelection();
const { tabSize, insertSpaces } = model.getOptions();
if (!editor || !editor.hasModel()) {
return undefined;
}
const { tabSize, insertSpaces } = editor.getModel().getOptions();
const workerService = accessor.get(IEditorWorkerService);
return editorSelection.isEmpty()
? getDocumentFormattingEdits(model, { tabSize, insertSpaces }, token)
: getDocumentRangeFormattingEdits(model, editorSelection, { tabSize, insertSpaces }, token);
}
}().run(accessor, editor);
if (editor.getSelection().isEmpty()) {
return formatDocument(workerService, editor, { tabSize, insertSpaces }, CancellationToken.None);
} else {
return formatDocumentRange(workerService, editor, FormatRangeType.Selection, { tabSize, insertSpaces }, CancellationToken.None);
}
return undefined;
});
......@@ -2787,6 +2787,11 @@ declare namespace monaco.editor {
* Defaults to 1.
*/
mouseWheelScrollSensitivity?: number;
/**
* FastScrolling mulitplier speed when pressing `Alt`
* Defaults to 5.
*/
fastScrollSensitivity?: number;
/**
* The modifier to be used to add multiple cursors with the mouse.
* Defaults to 'alt'
......@@ -3149,6 +3154,7 @@ declare namespace monaco.editor {
readonly verticalScrollbarSize: number;
readonly verticalSliderSize: number;
readonly mouseWheelScrollSensitivity: number;
readonly fastScrollSensitivity: number;
}
export interface InternalEditorMinimapOptions {
......
......@@ -243,7 +243,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
}, timeout);
request.then(edits => this._editorWorkerService.computeMoreMinimalEdits(model.uri, edits)).then(resolve, err => {
if (!(err instanceof Error) || err.name !== NoProviderError.Name) {
if (!NoProviderError.is(err)) {
reject(err);
} else {
resolve();
......
......@@ -128,8 +128,8 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
const debuggers = <IDebuggerContribution[]>ed.contributes['debuggers'];
if (debuggers && debuggers.length > 0) {
for (const dbg of debuggers) {
// only debugger contributions with a "label" are considered a "defining" debugger contribution
if (dbg.type && dbg.label) {
// only debugger contributions with a label, program, or runtime attribute are considered a "defining" debugger contribution
if (dbg.type && (dbg.label || dbg.program || dbg.runtime)) {
debugTypes.push(dbg.type);
if (dbg.adapterExecutableCommand) {
this._aexCommands.set(dbg.type, dbg.adapterExecutableCommand);
......
......@@ -42,37 +42,35 @@ export class Debugger implements IDebugger {
}
public createDebugAdapter(session: IDebugSession, outputService: IOutputService): Promise<IDebugAdapter> {
return new Promise<IDebugAdapter>((resolve, reject) => {
this.configurationManager.activateDebuggers('onDebugAdapterProtocolTracker', this.type).then(_ => {
resolve(this._createDebugAdapter(session, outputService));
}, reject);
});
}
private _createDebugAdapter(session: IDebugSession, outputService: IOutputService): Promise<IDebugAdapter> {
if (this.inExtHost()) {
return Promise.resolve(this.configurationManager.createDebugAdapter(session));
} else {
return this.getAdapterDescriptor(session).then(adapterDescriptor => {
switch (adapterDescriptor.type) {
case 'executable':
return new ExecutableDebugAdapter(adapterDescriptor, this.type, outputService);
case 'server':
return new SocketDebugAdapter(adapterDescriptor);
case 'implementation':
// TODO@AW: this.inExtHost() should now return true
return Promise.resolve(this.configurationManager.createDebugAdapter(session));
default:
throw new Error('unknown type');
}
}).catch(err => {
if (err && err.message) {
throw new Error(nls.localize('cannot.create.da.with.err', "Cannot create debug adapter ({0}).", err.message));
} else {
throw new Error(nls.localize('cannot.create.da', "Cannot create debug adapter."));
return this.configurationManager.activateDebuggers('onDebugAdapterProtocolTracker', this.type).then(_ => {
if (this.inExtHost()) {
const da = this.configurationManager.createDebugAdapter(session);
if (da) {
return Promise.resolve(da);
}
});
}
throw new Error(nls.localize('cannot.find.da', "Cannot find debug adapter for type '{0}'.", this.type));
} else {
return this.getAdapterDescriptor(session).then(adapterDescriptor => {
switch (adapterDescriptor.type) {
case 'executable':
return new ExecutableDebugAdapter(adapterDescriptor, this.type, outputService);
case 'server':
return new SocketDebugAdapter(adapterDescriptor);
case 'implementation':
// TODO@AW: this.inExtHost() should now return true
return Promise.resolve(this.configurationManager.createDebugAdapter(session));
default:
throw new Error('unknown descriptor type');
}
}).catch(err => {
if (err && err.message) {
throw new Error(nls.localize('cannot.create.da.with.err', "Cannot create debug adapter ({0}).", err.message));
} else {
throw new Error(nls.localize('cannot.create.da', "Cannot create debug adapter."));
}
});
}
});
}
private getAdapterDescriptor(session: IDebugSession): Promise<IAdapterDescriptor> {
......
......@@ -10,6 +10,6 @@ import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } fr
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { ExperimentalPrompts } from 'vs/workbench/parts/experiments/electron-browser/experimentalPrompt';
registerSingleton(IExperimentService, ExperimentService);
registerSingleton(IExperimentService, ExperimentService, true);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ExperimentalPrompts, LifecyclePhase.Eventually);
......@@ -50,7 +50,7 @@ import { ExtensionsAutoProfiler } from 'vs/workbench/parts/extensions/electron-b
// Singletons
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService);
registerSingleton(IExtensionTipsService, ExtensionTipsService);
registerSingleton(IExtensionHostProfileService, ExtensionHostProfileService);
registerSingleton(IExtensionHostProfileService, ExtensionHostProfileService, true);
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Restored);
......
......@@ -11,7 +11,7 @@ import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging';
import { Emitter, Event } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
import { domEvent } from 'vs/base/browser/event';
import { IExtension, IExtensionsWorkbenchService } from 'vs/workbench/parts/extensions/common/extensions';
import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, extensionButtonProminentBackground, extensionButtonProminentForeground, MaliciousStatusLabelAction, ExtensionActionItem } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
......@@ -22,9 +22,9 @@ import { IExtensionTipsService, IExtensionManagementServerService } from 'vs/pla
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { INotificationService } from 'vs/platform/notification/common/notification';
export interface IExtensionWithFocus extends IExtension {
onDidFocusChange?: Event<boolean>;
onFocusChangeEventEmitter?: Emitter<boolean>;
export interface IExtensionsViewState {
onFocus: Event<IExtension>;
onBlur: Event<IExtension>;
}
export interface ITemplateData {
......@@ -52,6 +52,7 @@ const actionOptions = { icon: true, label: true, tabOnlyOnFocus: true };
export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
constructor(
private extensionViewState: IExtensionsViewState,
@IInstantiationService private instantiationService: IInstantiationService,
@INotificationService private notificationService: INotificationService,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
......@@ -141,7 +142,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
data.extension = null;
}
renderElement(extension: IExtensionWithFocus, index: number, data: ITemplateData): void {
renderElement(extension: IExtension, index: number, data: ITemplateData): void {
removeClass(data.element, 'loading');
data.extensionDisposables = dispose(data.extensionDisposables);
......@@ -195,13 +196,17 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
data.description.textContent = extension.gallery.properties.localizedLanguages.map(name => name[0].toLocaleUpperCase() + name.slice(1)).join(', ');
}
if (extension.onDidFocusChange) {
data.extensionDisposables.push(extension.onDidFocusChange(hasFocus => {
data.actionbar.items.forEach(item => {
(<ExtensionActionItem>item).setFocus(hasFocus);
});
}));
}
this.extensionViewState.onFocus(e => {
if (areSameExtensions(extension, e)) {
data.actionbar.items.forEach(item => (<ExtensionActionItem>item).setFocus(true));
}
}, this, data.extensionDisposables);
this.extensionViewState.onBlur(e => {
if (areSameExtensions(extension, e)) {
data.actionbar.items.forEach(item => (<ExtensionActionItem>item).setFocus(false));
}
}, this, data.extensionDisposables);
}
private updateRecommendationStatus(extension: IExtension, data: ITemplateData) {
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { dispose } from 'vs/base/common/lifecycle';
import { dispose, Disposable } from 'vs/base/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import { Event, Emitter } from 'vs/base/common/event';
import { isPromiseCanceledError } from 'vs/base/common/errors';
......@@ -15,8 +15,8 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { append, $, toggleClass } from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Delegate, Renderer, IExtensionWithFocus as IExtension } from 'vs/workbench/parts/extensions/electron-browser/extensionsList';
import { IExtension as IExtensionBase, IExtensionsWorkbenchService } from '../common/extensions';
import { Delegate, Renderer, IExtensionsViewState } from 'vs/workbench/parts/extensions/electron-browser/extensionsList';
import { IExtension, IExtensionsWorkbenchService } from '../common/extensions';
import { Query } from '../common/extensionQuery';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IThemeService } from 'vs/platform/theme/common/themeService';
......@@ -37,12 +37,29 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { distinct } from 'vs/base/common/arrays';
import { IExperimentService, IExperiment, ExperimentActionType } from 'vs/workbench/parts/experiments/node/experimentService';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { IListContextMenuEvent, IListEvent } from 'vs/base/browser/ui/list/list';
import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
import { CancellationToken } from 'vs/base/common/cancellation';
import { getKeywordsForExtension } from 'vs/workbench/parts/extensions/electron-browser/extensionsUtils';
import { IAction } from 'vs/base/common/actions';
class ExtensionsViewState extends Disposable implements IExtensionsViewState {
private readonly _onFocus: Emitter<IExtension> = this._register(new Emitter<IExtension>());
readonly onFocus: Event<IExtension> = this._onFocus.event;
private readonly _onBlur: Emitter<IExtension> = this._register(new Emitter<IExtension>());
readonly onBlur: Event<IExtension> = this._onBlur.event;
private currentlyFocusedItems: IExtension[] = [];
onFocusChange(extensions: IExtension[]): void {
this.currentlyFocusedItems.forEach(extension => this._onBlur.fire(extension));
this.currentlyFocusedItems = extensions;
this.currentlyFocusedItems.forEach(extension => this._onFocus.fire(extension));
}
}
export class ExtensionsListView extends ViewletPanel {
private messageBox: HTMLElement;
......@@ -87,15 +104,17 @@ export class ExtensionsListView extends ViewletPanel {
this.extensionsList = append(container, $('.extensions-list'));
this.messageBox = append(container, $('.message'));
const delegate = new Delegate();
const renderer = this.instantiationService.createInstance(Renderer);
const extensionsViewState = new ExtensionsViewState();
const renderer = this.instantiationService.createInstance(Renderer, extensionsViewState);
this.list = this.instantiationService.createInstance(WorkbenchPagedList, this.extensionsList, delegate, [renderer], {
ariaLabel: localize('extensions', "Extensions"),
multipleSelectionSupport: false,
setRowLineHeight: false
}) as WorkbenchPagedList<IExtension>;
this.list.onContextMenu(e => this.onContextMenu(e), this, this.disposables);
this.list.onFocusChange(e => this.onFocusChange(e), this, this.disposables);
this.list.onFocusChange(e => extensionsViewState.onFocusChange(e.elements), this, this.disposables);
this.disposables.push(this.list);
this.disposables.push(extensionsViewState);
Event.chain(this.list.onOpen)
.map(e => e.elements[0])
......@@ -154,13 +173,6 @@ export class ExtensionsListView extends ViewletPanel {
return Promise.resolve(emptyModel);
}
private currentlyFocusedItems: IExtension[] = [];
private onFocusChange(e: IListEvent<IExtension>): void {
this.currentlyFocusedItems.forEach(item => item.onFocusChangeEventEmitter.fire(false));
this.currentlyFocusedItems = e.elements;
this.currentlyFocusedItems.forEach(item => item.onFocusChangeEventEmitter.fire(true));
}
private onContextMenu(e: IListContextMenuEvent<IExtension>): void {
if (e.element) {
this.extensionService.getExtensions()
......@@ -660,28 +672,15 @@ export class ExtensionsListView extends ViewletPanel {
this.notificationService.error(err);
}
private getPagedModel(arg: IPager<IExtensionBase> | IExtensionBase[]): IPagedModel<IExtension> {
const convert = (ext: IExtension): IExtension => {
const eventEmitter = new Emitter<boolean>();
const extFocus: IExtension = ext;
extFocus.onFocusChangeEventEmitter = eventEmitter;
extFocus.onDidFocusChange = eventEmitter.event;
return extFocus;
};
private getPagedModel(arg: IPager<IExtension> | IExtension[]): IPagedModel<IExtension> {
if (Array.isArray(arg)) {
return new PagedModel(arg.map(ext => convert(ext)));
return new PagedModel(arg);
}
const pager = {
total: arg.total,
pageSize: arg.pageSize,
firstPage: arg.firstPage.map(ext => convert(ext)),
getPage: (pageIndex: number, cancellationToken: CancellationToken) => {
return arg.getPage(pageIndex, cancellationToken).then(extensions => {
return extensions.map(ext => convert(ext));
});
}
firstPage: arg.firstPage,
getPage: (pageIndex: number, cancellationToken: CancellationToken) => arg.getPage(pageIndex, cancellationToken)
};
return new PagedModel(pager);
}
......
......@@ -220,6 +220,7 @@ export class MarkersFilterActionItem extends BaseActionItem {
this._register(filesExcludeFilter.onChange(() => {
filesExcludeFilter.domNode.title = filesExcludeFilter.checked ? Messages.MARKERS_PANEL_ACTION_TOOLTIP_DO_NOT_USE_FILES_EXCLUDE : Messages.MARKERS_PANEL_ACTION_TOOLTIP_USE_FILES_EXCLUDE;
this.action.useFilesExclude = filesExcludeFilter.checked;
this.focus();
}));
this._register(this.action.onDidChange((event: IMarkersFilterActionChangeEvent) => {
if (event.useFilesExclude) {
......
......@@ -441,7 +441,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
}
const enableProposedApiForAll = !this._environmentService.isBuilt ||
(!!this._environmentService.extensionDevelopmentLocationURI && product.nameLong.indexOf('Insiders') >= 0) ||
(!!this._environmentService.extensionDevelopmentLocationURI && product.nameLong !== 'Visual Studio Code') ||
(enableProposedApiFor.length === 0 && 'enable-proposed-api' in this._environmentService.args);
for (const extension of allExtensions) {
......
......@@ -453,7 +453,7 @@ export class DefaultSettings extends Disposable {
getContent(forceUpdate = false): string {
if (!this._content || forceUpdate) {
this._content = this.toContent(true, this.getSettingsGroups(forceUpdate));
this.initialize();
}
return this._content;
......@@ -461,12 +461,17 @@ export class DefaultSettings extends Disposable {
getSettingsGroups(forceUpdate = false): ISettingsGroup[] {
if (!this._allSettingsGroups || forceUpdate) {
this._allSettingsGroups = this.parse();
this.initialize();
}
return this._allSettingsGroups;
}
private initialize(): void {
this._allSettingsGroups = this.parse();
this._content = this.toContent(true, this._allSettingsGroups);
}
private parse(): ISettingsGroup[] {
const settingsGroups = this.getRegisteredGroups();
this.initAllSettingsMap(settingsGroups);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册