Merge from vscode a4177f50c475fc0fa278a78235e3bee9ffdec781 (#8649)

* Merge from vscode a4177f50c475fc0fa278a78235e3bee9ffdec781

* distro

* fix tests
This commit is contained in:
Anthony Dresser
2019-12-11 22:42:23 -08:00
committed by GitHub
parent 82974a2135
commit 4ba6a979ba
280 changed files with 10898 additions and 14231 deletions

View File

@@ -20,7 +20,7 @@ import { IConstructorSignature1, ServicesAccessor as InstantiationServicesAccess
import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { withNullAsUndefined } from 'vs/base/common/types';
import { withNullAsUndefined, assertType } from 'vs/base/common/types';
export type ServicesAccessor = InstantiationServicesAccessor;
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, IEditorContribution>;
@@ -311,6 +311,60 @@ export function registerDefaultLanguageCommand(id: string, handler: (model: ITex
});
}
export function registerModelAndPositionCommand(id: string, handler: (model: ITextModel, position: Position, ...args: any[]) => any) {
CommandsRegistry.registerCommand(id, function (accessor, ...args) {
const [resource, position] = args;
assertType(URI.isUri(resource));
assertType(Position.isIPosition(position));
const model = accessor.get(IModelService).getModel(resource);
if (model) {
const editorPosition = Position.lift(position);
return handler(model, editorPosition, args.slice(2));
}
return accessor.get(ITextModelService).createModelReference(resource).then(reference => {
return new Promise((resolve, reject) => {
try {
const result = handler(reference.object.textEditorModel, Position.lift(position), args.slice(2));
resolve(result);
} catch (err) {
reject(err);
}
}).finally(() => {
reference.dispose();
});
});
});
}
export function registerModelCommand(id: string, handler: (model: ITextModel, ...args: any[]) => any) {
CommandsRegistry.registerCommand(id, function (accessor, ...args) {
const [resource] = args;
assertType(URI.isUri(resource));
const model = accessor.get(IModelService).getModel(resource);
if (model) {
return handler(model, args.slice(1));
}
return accessor.get(ITextModelService).createModelReference(resource).then(reference => {
return new Promise((resolve, reject) => {
try {
const result = handler(reference.object.textEditorModel, args.slice(1));
resolve(result);
} catch (err) {
reject(err);
}
}).finally(() => {
reference.dispose();
});
});
});
}
export function registerEditorCommand<T extends EditorCommand>(editorCommand: T): T {
EditorContributionRegistry.INSTANCE.registerEditorCommand(editorCommand);
return editorCommand;

View File

@@ -50,6 +50,7 @@ export class EditorScrollbar extends ViewPart {
horizontalScrollbarSize: scrollbar.horizontalScrollbarSize,
horizontalSliderSize: scrollbar.horizontalSliderSize,
handleMouseWheel: scrollbar.handleMouseWheel,
alwaysConsumeMouseWheel: scrollbar.alwaysConsumeMouseWheel,
arrowSize: scrollbar.arrowSize,
mouseWheelScrollSensitivity: mouseWheelScrollSensitivity,
fastScrollSensitivity: fastScrollSensitivity,

View File

@@ -417,9 +417,12 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
// Current model is the new model
return;
}
const hasTextFocus = this.hasTextFocus();
const detachedModel = this._detachModel();
this._attachModel(model);
if (hasTextFocus && this.hasModel()) {
this.focus();
}
const e: editorCommon.IModelChangedEvent = {
oldModelUrl: detachedModel ? detachedModel.uri : null,

View File

@@ -2327,6 +2327,11 @@ export interface IEditorScrollbarOptions {
* Defaults to true.
*/
handleMouseWheel?: boolean;
/**
* Always consume mouse wheel events (always call preventDefault() and stopPropagation() on the browser events).
* Defaults to true.
*/
alwaysConsumeMouseWheel?: boolean;
/**
* Height in pixels for the horizontal scrollbar.
* Defaults to 10 (px).
@@ -2357,6 +2362,7 @@ export interface InternalEditorScrollbarOptions {
readonly verticalHasArrows: boolean;
readonly horizontalHasArrows: boolean;
readonly handleMouseWheel: boolean;
readonly alwaysConsumeMouseWheel: boolean;
readonly horizontalScrollbarSize: number;
readonly horizontalSliderSize: number;
readonly verticalScrollbarSize: number;
@@ -2391,6 +2397,7 @@ class EditorScrollbar extends BaseEditorOption<EditorOption.scrollbar, InternalE
verticalScrollbarSize: 14,
verticalSliderSize: 14,
handleMouseWheel: true,
alwaysConsumeMouseWheel: true
}
);
}
@@ -2410,6 +2417,7 @@ class EditorScrollbar extends BaseEditorOption<EditorOption.scrollbar, InternalE
verticalHasArrows: EditorBooleanOption.boolean(input.verticalHasArrows, this.defaultValue.verticalHasArrows),
horizontalHasArrows: EditorBooleanOption.boolean(input.horizontalHasArrows, this.defaultValue.horizontalHasArrows),
handleMouseWheel: EditorBooleanOption.boolean(input.handleMouseWheel, this.defaultValue.handleMouseWheel),
alwaysConsumeMouseWheel: EditorBooleanOption.boolean(input.alwaysConsumeMouseWheel, this.defaultValue.alwaysConsumeMouseWheel),
horizontalScrollbarSize: horizontalScrollbarSize,
horizontalSliderSize: EditorIntOption.clampedInt(input.horizontalSliderSize, horizontalScrollbarSize, 0, 1000),
verticalScrollbarSize: verticalScrollbarSize,
@@ -3358,7 +3366,7 @@ export const EditorOptions = {
lineNumbers: register(new EditorRenderLineNumbersOption()),
lineNumbersMinChars: register(new EditorIntOption(
EditorOption.lineNumbersMinChars, 'lineNumbersMinChars',
5, 1, 10
5, 1, 300
)),
links: register(new EditorBooleanOption(
EditorOption.links, 'links', true,

View File

@@ -386,7 +386,7 @@ export class TextModelResolvedOptions {
defaultEOL: DefaultEndOfLine;
trimAutoWhitespace: boolean;
}) {
this.tabSize = src.tabSize | 0;
this.tabSize = Math.max(1, src.tabSize | 0);
this.indentSize = src.tabSize | 0;
this.insertSpaces = Boolean(src.insertSpaces);
this.defaultEOL = src.defaultEOL | 0;

View File

@@ -1246,9 +1246,9 @@ export function isResourceTextEdit(thing: any): thing is ResourceTextEdit {
}
export interface ResourceFileEdit {
oldUri: URI;
newUri: URI;
options: { overwrite?: boolean, ignoreIfNotExists?: boolean, ignoreIfExists?: boolean, recursive?: boolean };
oldUri?: URI;
newUri?: URI;
options?: { overwrite?: boolean, ignoreIfNotExists?: boolean, ignoreIfExists?: boolean, recursive?: boolean };
}
export interface ResourceTextEdit {

View File

@@ -5,7 +5,8 @@
import 'vs/css!./codelensWidget';
import * as dom from 'vs/base/browser/dom';
import { renderCodicons } from 'vs/base/browser/ui/codiconLabel/codiconLabel';
import { renderCodicons } from 'vs/base/common/codicons';
import { escape } from 'vs/base/common/strings';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { Range } from 'vs/editor/common/core/range';
import { IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
@@ -88,7 +89,7 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
}
hasSymbol = true;
if (lens.command) {
const title = renderCodicons(lens.command.title);
const title = renderCodicons(escape(lens.command.title));
if (lens.command.id) {
innerHtml += `<a id=${i}>${title}</a>`;
this._commands.set(String(i), lens.command);

View File

@@ -10,7 +10,7 @@ import { illegalArgument, onUnexpectedExternalError } from 'vs/base/common/error
import { URI } from 'vs/base/common/uri';
import { CodeEditorStateFlag, EditorStateCancellationTokenSource, TextModelCancellationTokenSource } from 'vs/editor/browser/core/editorState';
import { IActiveCodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { registerLanguageCommand, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
@@ -25,6 +25,8 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable } from 'vs/base/common/lifecycle';
import { LinkedList } from 'vs/base/common/linkedList';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { assertType } from 'vs/base/common/types';
export function alertFormattingEdits(edits: ISingleEditOperation[]): void {
@@ -354,11 +356,11 @@ export function getOnTypeFormattingEdits(
});
}
registerLanguageCommand('_executeFormatRangeProvider', function (accessor, args) {
const { resource, range, options } = args;
if (!(resource instanceof URI) || !Range.isIRange(range)) {
throw illegalArgument();
}
CommandsRegistry.registerCommand('_executeFormatRangeProvider', function (accessor, ...args) {
const [resource, range, options] = args;
assertType(URI.isUri(resource));
assertType(Range.isIRange(range));
const model = accessor.get(IModelService).getModel(resource);
if (!model) {
throw illegalArgument('resource');
@@ -366,11 +368,10 @@ registerLanguageCommand('_executeFormatRangeProvider', function (accessor, args)
return getDocumentRangeFormattingEditsUntilResult(accessor.get(IEditorWorkerService), model, Range.lift(range), options, CancellationToken.None);
});
registerLanguageCommand('_executeFormatDocumentProvider', function (accessor, args) {
const { resource, options } = args;
if (!(resource instanceof URI)) {
throw illegalArgument('resource');
}
CommandsRegistry.registerCommand('_executeFormatDocumentProvider', function (accessor, ...args) {
const [resource, options] = args;
assertType(URI.isUri(resource));
const model = accessor.get(IModelService).getModel(resource);
if (!model) {
throw illegalArgument('resource');
@@ -379,11 +380,12 @@ registerLanguageCommand('_executeFormatDocumentProvider', function (accessor, ar
return getDocumentFormattingEditsUntilResult(accessor.get(IEditorWorkerService), model, options, CancellationToken.None);
});
registerLanguageCommand('_executeFormatOnTypeProvider', function (accessor, args) {
const { resource, position, ch, options } = args;
if (!(resource instanceof URI) || !Position.isIPosition(position) || typeof ch !== 'string') {
throw illegalArgument();
}
CommandsRegistry.registerCommand('_executeFormatOnTypeProvider', function (accessor, ...args) {
const [resource, position, ch, options] = args;
assertType(URI.isUri(resource));
assertType(Position.isIPosition(position));
assertType(typeof ch === 'string');
const model = accessor.get(IModelService).getModel(resource);
if (!model) {
throw illegalArgument('resource');

View File

@@ -6,7 +6,7 @@
import { flatten, coalesce } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { onUnexpectedExternalError } from 'vs/base/common/errors';
import { registerDefaultLanguageCommand } from 'vs/editor/browser/editorExtensions';
import { registerModelAndPositionCommand } from 'vs/editor/browser/editorExtensions';
import { Position } from 'vs/editor/common/core/position';
import { ITextModel } from 'vs/editor/common/model';
import { LocationLink, DefinitionProviderRegistry, ImplementationProviderRegistry, TypeDefinitionProviderRegistry, DeclarationProviderRegistry, ProviderResult, ReferenceProviderRegistry } from 'vs/editor/common/modes';
@@ -72,8 +72,8 @@ export function getReferencesAtPosition(model: ITextModel, position: Position, c
});
}
registerDefaultLanguageCommand('_executeDefinitionProvider', (model, position) => getDefinitionsAtPosition(model, position, CancellationToken.None));
registerDefaultLanguageCommand('_executeDeclarationProvider', (model, position) => getDeclarationsAtPosition(model, position, CancellationToken.None));
registerDefaultLanguageCommand('_executeImplementationProvider', (model, position) => getImplementationsAtPosition(model, position, CancellationToken.None));
registerDefaultLanguageCommand('_executeTypeDefinitionProvider', (model, position) => getTypeDefinitionsAtPosition(model, position, CancellationToken.None));
registerDefaultLanguageCommand('_executeReferenceProvider', (model, position) => getReferencesAtPosition(model, position, false, CancellationToken.None));
registerModelAndPositionCommand('_executeDefinitionProvider', (model, position) => getDefinitionsAtPosition(model, position, CancellationToken.None));
registerModelAndPositionCommand('_executeDeclarationProvider', (model, position) => getDeclarationsAtPosition(model, position, CancellationToken.None));
registerModelAndPositionCommand('_executeImplementationProvider', (model, position) => getImplementationsAtPosition(model, position, CancellationToken.None));
registerModelAndPositionCommand('_executeTypeDefinitionProvider', (model, position) => getTypeDefinitionsAtPosition(model, position, CancellationToken.None));
registerModelAndPositionCommand('_executeReferenceProvider', (model, position) => getReferencesAtPosition(model, position, false, CancellationToken.None));

View File

@@ -23,7 +23,7 @@ import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async
import { getOuterEditor, PeekContext } from 'vs/editor/contrib/peekView/peekView';
import { IListService, WorkbenchListFocusContextKey } from 'vs/platform/list/browser/listService';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { KeyCode, KeyMod, KeyChord } from 'vs/base/common/keyCodes';
export const ctxReferenceSearchVisible = new RawContextKey<boolean>('referenceSearchVisible', false);
@@ -173,6 +173,18 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
});
}
changeFocusBetweenPreviewAndReferences() {
if (!this._widget) {
// can be called while still resolving...
return;
}
if (this._widget.isPreviewEditorFocused()) {
this._widget.focusOnReferenceTree();
} else {
this._widget.focusOnPreviewEditor();
}
}
async goToNextOrPreviousReference(fwd: boolean) {
if (!this._editor.hasModel() || !this._model || !this._widget) {
// can be called while still resolving...
@@ -229,7 +241,7 @@ export abstract class ReferencesController implements editorCommon.IEditorContri
if (this._editor === openedEditor) {
//
this._widget.show(range);
this._widget.focus();
this._widget.focusOnReferenceTree();
} else {
// we opened a different editor instance which means a different controller instance.
@@ -278,6 +290,18 @@ function withController(accessor: ServicesAccessor, fn: (controller: ReferencesC
}
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'changePeekFocus',
weight: KeybindingWeight.WorkbenchContrib + 50,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.F2),
when: ContextKeyExpr.or(ctxReferenceSearchVisible, PeekContext.inPeekEditor),
handler(accessor) {
withController(accessor, controller => {
controller.changeFocusBetweenPreviewAndReferences();
});
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'goToNextReference',
weight: KeybindingWeight.WorkbenchContrib + 50,

View File

@@ -251,10 +251,18 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
super.show(where, this.layoutData.heightInLines || 18);
}
focus(): void {
focusOnReferenceTree(): void {
this._tree.domFocus();
}
focusOnPreviewEditor(): void {
this._preview.focus();
}
isPreviewEditorFocused(): boolean {
return this._preview.hasTextFocus();
}
protected _onTitleClick(e: IMouseEvent): void {
if (this._preview && this._preview.getModel()) {
this._onDidSelectReference.fire({
@@ -283,7 +291,8 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
horizontal: 'auto',
useShadows: true,
verticalHasArrows: false,
horizontalHasArrows: false
horizontalHasArrows: false,
alwaysConsumeMouseWheel: false
},
overviewRulerLanes: 2,
fixedOverflowWidgets: true,
@@ -457,7 +466,7 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
dom.show(this._treeContainer);
dom.show(this._previewContainer);
this._splitView.layout(this._dim.width);
this.focus();
this.focusOnReferenceTree();
// pick input and a reference to begin with
return this._tree.setInput(this._model.groups.length === 1 ? this._model.groups[0] : this._model);

View File

@@ -6,7 +6,7 @@
import { coalesce } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { onUnexpectedExternalError } from 'vs/base/common/errors';
import { registerDefaultLanguageCommand } from 'vs/editor/browser/editorExtensions';
import { registerModelAndPositionCommand } from 'vs/editor/browser/editorExtensions';
import { Position } from 'vs/editor/common/core/position';
import { ITextModel } from 'vs/editor/common/model';
import { Hover, HoverProviderRegistry } from 'vs/editor/common/modes';
@@ -27,7 +27,7 @@ export function getHover(model: ITextModel, position: Position, token: Cancellat
return Promise.all(promises).then(coalesce);
}
registerDefaultLanguageCommand('_executeHoverProvider', (model, position) => getHover(model, position, CancellationToken.None));
registerModelAndPositionCommand('_executeHoverProvider', (model, position) => getHover(model, position, CancellationToken.None));
function isValid(result: Hover) {
const hasRange = (typeof result.range !== 'undefined');

View File

@@ -19,7 +19,7 @@ export class ContentHoverWidget extends Widget implements IContentWidget {
protected _editor: ICodeEditor;
private _isVisible: boolean;
private readonly _containerDomNode: HTMLElement;
private readonly _domNode: HTMLElement;
protected readonly _domNode: HTMLElement;
protected _showAtPosition: Position | null;
protected _showAtRange: Range | null;
private _stoleFocus: boolean;

View File

@@ -13,7 +13,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { Position } from 'vs/editor/common/core/position';
import { IRange, Range } from 'vs/editor/common/core/range';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { DocumentColorProvider, Hover as MarkdownHover, HoverProviderRegistry, IColor } from 'vs/editor/common/modes';
import { DocumentColorProvider, Hover as MarkdownHover, HoverProviderRegistry, IColor, TokenizationRegistry } from 'vs/editor/common/modes';
import { getColorPresentations } from 'vs/editor/contrib/colorPicker/color';
import { ColorDetector } from 'vs/editor/contrib/colorPicker/colorDetector';
import { ColorPickerModel } from 'vs/editor/contrib/colorPicker/colorPickerModel';
@@ -238,6 +238,12 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
this._register(editor.onDidChangeConfiguration((e) => {
this._hoverOperation.setHoverTime(this._editor.getOption(EditorOption.hover).delay);
}));
this._register(TokenizationRegistry.onDidChange((e) => {
if (this.isVisible && this._lastRange && this._messages.length > 0) {
this._domNode.textContent = '';
this._renderMessages(this._lastRange, this._messages);
}
}));
}
dispose(): void {

View File

@@ -176,7 +176,7 @@ class MessageWidget implements IContentWidget {
}
getPosition(): IContentWidgetPosition {
return { position: this._position, preference: [ContentWidgetPositionPreference.ABOVE] };
return { position: this._position, preference: [ContentWidgetPositionPreference.ABOVE, ContentWidgetPositionPreference.BELOW] };
}
}

View File

@@ -54,6 +54,10 @@
white-space: initial;
}
.monaco-editor .parameter-hints-widget .docs .markdown-docs p code {
font-family: var(--monaco-monospace-font);
}
.monaco-editor .parameter-hints-widget .docs .code {
white-space: pre-wrap;
}

View File

@@ -3,17 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { illegalArgument } from 'vs/base/common/errors';
import { URI } from 'vs/base/common/uri';
import { Range } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions';
import { DocumentSymbol } from 'vs/editor/common/modes';
import { IModelService } from 'vs/editor/common/services/modelService';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { OutlineModel, OutlineElement } from 'vs/editor/contrib/documentSymbols/outlineModel';
import { values } from 'vs/base/common/collections';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { assertType } from 'vs/base/common/types';
export async function getDocumentSymbols(document: ITextModel, flat: boolean, token: CancellationToken): Promise<DocumentSymbol[]> {
@@ -63,26 +63,19 @@ function flatten(bucket: DocumentSymbol[], entries: DocumentSymbol[], overrideCo
}
registerLanguageCommand('_executeDocumentSymbolProvider', function (accessor, args) {
const { resource } = args;
if (!(resource instanceof URI)) {
throw illegalArgument('resource');
}
CommandsRegistry.registerCommand('_executeDocumentSymbolProvider', async function (accessor, ...args) {
const [resource] = args;
assertType(URI.isUri(resource));
const model = accessor.get(IModelService).getModel(resource);
if (model) {
return getDocumentSymbols(model, false, CancellationToken.None);
}
return accessor.get(ITextModelService).createModelReference(resource).then(reference => {
return new Promise((resolve, reject) => {
try {
const result = getDocumentSymbols(reference.object.textEditorModel, false, CancellationToken.None);
resolve(result);
} catch (err) {
reject(err);
}
}).finally(() => {
reference.dispose();
});
});
const reference = await accessor.get(ITextModelService).createModelReference(resource);
try {
return await getDocumentSymbols(reference.object.textEditorModel, false, CancellationToken.None);
} finally {
reference.dispose();
}
});

View File

@@ -7,7 +7,7 @@ import * as arrays from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, IActionOptions, registerEditorAction, registerEditorContribution, ServicesAccessor, registerDefaultLanguageCommand } from 'vs/editor/browser/editorExtensions';
import { EditorAction, IActionOptions, registerEditorAction, registerEditorContribution, ServicesAccessor, registerModelCommand } from 'vs/editor/browser/editorExtensions';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
@@ -302,6 +302,7 @@ export function provideSelectionRanges(model: ITextModel, positions: Position[],
});
}
registerDefaultLanguageCommand('_executeSelectionRangeProvider', function (model, _position, args) {
return provideSelectionRanges(model, args.positions, CancellationToken.None);
registerModelCommand('_executeSelectionRangeProvider', function (model, ...args) {
const [positions] = args;
return provideSelectionRanges(model, positions, CancellationToken.None);
});

View File

@@ -21,6 +21,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { WordDistance } from 'vs/editor/contrib/suggest/wordDistance';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { isLowSurrogate, isHighSurrogate } from 'vs/base/common/strings';
export interface ICancelEvent {
readonly retrigger: boolean;
@@ -95,7 +96,7 @@ export class SuggestModel implements IDisposable {
private readonly _toDispose = new DisposableStore();
private _quickSuggestDelay: number = 10;
private _triggerCharacterListener?: IDisposable;
private readonly _triggerCharacterListener = new DisposableStore();
private readonly _triggerQuickSuggest = new TimeoutTimer();
private _state: State = State.Idle;
@@ -181,8 +182,7 @@ export class SuggestModel implements IDisposable {
}
private _updateTriggerCharacters(): void {
dispose(this._triggerCharacterListener);
this._triggerCharacterListener.clear();
if (this._editor.getOption(EditorOption.readOnly)
|| !this._editor.hasModel()
@@ -191,29 +191,49 @@ export class SuggestModel implements IDisposable {
return;
}
const supportsByTriggerCharacter: { [ch: string]: Set<CompletionItemProvider> } = Object.create(null);
const supportsByTriggerCharacter = new Map<string, Set<CompletionItemProvider>>();
for (const support of CompletionProviderRegistry.all(this._editor.getModel())) {
for (const ch of support.triggerCharacters || []) {
let set = supportsByTriggerCharacter[ch];
let set = supportsByTriggerCharacter.get(ch);
if (!set) {
set = supportsByTriggerCharacter[ch] = new Set();
set = new Set();
set.add(getSnippetSuggestSupport());
supportsByTriggerCharacter.set(ch, set);
}
set.add(support);
}
}
this._triggerCharacterListener = this._editor.onDidType(text => {
const lastChar = text.charAt(text.length - 1);
const supports = supportsByTriggerCharacter[lastChar];
const checkTriggerCharacter = (text?: string) => {
if (!text) {
// came here from the compositionEnd-event
const position = this._editor.getPosition()!;
const model = this._editor.getModel()!;
text = model.getLineContent(position.lineNumber).substr(0, position.column - 1);
}
let lastChar = '';
if (isLowSurrogate(text.charCodeAt(text.length - 1))) {
if (isHighSurrogate(text.charCodeAt(text.length - 2))) {
lastChar = text.substr(text.length - 2);
}
} else {
lastChar = text.charAt(text.length - 1);
}
const supports = supportsByTriggerCharacter.get(lastChar);
if (supports) {
// keep existing items that where not computed by the
// supports/providers that want to trigger now
const items: CompletionItem[] | undefined = this._completionModel ? this._completionModel.adopt(supports) : undefined;
this.trigger({ auto: true, shy: false, triggerCharacter: lastChar }, Boolean(this._completionModel), supports, items);
}
});
};
this._triggerCharacterListener.add(this._editor.onDidType(checkTriggerCharacter));
this._triggerCharacterListener.add(this._editor.onCompositionEnd(checkTriggerCharacter));
}
// --- trigger/retrigger/cancel suggest

View File

@@ -11,7 +11,7 @@ import { onUnexpectedError, onUnexpectedExternalError } from 'vs/base/common/err
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IActiveCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, IActionOptions, registerDefaultLanguageCommand, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { EditorAction, IActionOptions, registerEditorAction, registerEditorContribution, registerModelAndPositionCommand } from 'vs/editor/browser/editorExtensions';
import { CursorChangeReason, ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
@@ -155,7 +155,7 @@ function computeOccurencesAtPosition(model: ITextModel, selection: Selection, wo
return new TextualOccurenceAtPositionRequest(model, selection, wordSeparators);
}
registerDefaultLanguageCommand('_executeDocumentHighlights', (model, position) => getOccurrencesAtPosition(model, position, CancellationToken.None));
registerModelAndPositionCommand('_executeDocumentHighlights', (model, position) => getOccurrencesAtPosition(model, position, CancellationToken.None));
class WordHighlighter {

View File

@@ -305,6 +305,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService {
let shouldPreventDefault = this._dispatch(keyEvent, keyEvent.target);
if (shouldPreventDefault) {
keyEvent.preventDefault();
keyEvent.stopPropagation();
}
}));
}

View File

@@ -424,7 +424,7 @@ export function registerCodeLensProvider(languageId: string, provider: modes.Cod
*/
export function registerCodeActionProvider(languageId: string, provider: CodeActionProvider): IDisposable {
return modes.CodeActionProviderRegistry.register(languageId, {
provideCodeActions: (model: model.ITextModel, range: Range, context: modes.CodeActionContext, token: CancellationToken): modes.CodeActionList | Promise<modes.CodeActionList> => {
provideCodeActions: (model: model.ITextModel, range: Range, context: modes.CodeActionContext, token: CancellationToken): modes.ProviderResult<modes.CodeActionList> => {
let markers = StaticServices.markerService.get().read({ resource: model.uri }).filter(m => {
return Range.areIntersectingOrTouching(m, range);
});
@@ -521,7 +521,7 @@ export interface CodeActionProvider {
/**
* Provide commands for the given document and range.
*/
provideCodeActions(model: model.ITextModel, range: Range, context: CodeActionContext, token: CancellationToken): modes.CodeActionList | Promise<modes.CodeActionList>;
provideCodeActions(model: model.ITextModel, range: Range, context: CodeActionContext, token: CancellationToken): modes.ProviderResult<modes.CodeActionList>;
}
/**

View File

@@ -60,6 +60,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
verticalHasArrows: input.verticalScrollbarHasArrows,
horizontalHasArrows: false,
handleMouseWheel: EditorOptions.scrollbar.defaultValue.handleMouseWheel,
alwaysConsumeMouseWheel: true,
horizontalScrollbarSize: input.horizontalScrollbarHeight,
horizontalSliderSize: EditorOptions.scrollbar.defaultValue.horizontalSliderSize,
verticalScrollbarSize: input.verticalScrollbarWidth,