Merge VS Code 1.23.1 (#1520)

This commit is contained in:
Matt Irvine
2018-06-05 11:24:51 -07:00
committed by GitHub
parent e3baf5c443
commit 0c58f09e59
3651 changed files with 74249 additions and 48599 deletions

View File

@@ -0,0 +1,338 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, EditorCommand, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { BulkEdit } from 'vs/editor/browser/services/bulkEdit';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { CodeAction } from 'vs/editor/common/modes';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { MessageController } from 'vs/editor/contrib/message/messageController';
import * as nls from 'vs/nls';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IFileService } from 'vs/platform/files/common/files';
import { optional } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IMarkerService } from 'vs/platform/markers/common/markers';
import { CodeActionModel, CodeActionsComputeEvent, SUPPORTED_CODE_ACTIONS } from './codeActionModel';
import { CodeActionAutoApply, CodeActionFilter, CodeActionKind } from './codeActionTrigger';
import { CodeActionContextMenu } from './codeActionWidget';
import { LightBulbWidget } from './lightBulbWidget';
import { escapeRegExpCharacters } from 'vs/base/common/strings';
function contextKeyForSupportedActions(kind: CodeActionKind) {
return ContextKeyExpr.regex(
SUPPORTED_CODE_ACTIONS.keys()[0],
new RegExp('(\\s|^)' + escapeRegExpCharacters(kind.value) + '\\b'));
}
export class QuickFixController implements IEditorContribution {
private static readonly ID = 'editor.contrib.quickFixController';
public static get(editor: ICodeEditor): QuickFixController {
return editor.getContribution<QuickFixController>(QuickFixController.ID);
}
private _editor: ICodeEditor;
private _model: CodeActionModel;
private _codeActionContextMenu: CodeActionContextMenu;
private _lightBulbWidget: LightBulbWidget;
private _disposables: IDisposable[] = [];
constructor(editor: ICodeEditor,
@IMarkerService markerService: IMarkerService,
@IContextKeyService contextKeyService: IContextKeyService,
@ICommandService private readonly _commandService: ICommandService,
@IContextMenuService contextMenuService: IContextMenuService,
@IKeybindingService private readonly _keybindingService: IKeybindingService,
@ITextModelService private readonly _textModelService: ITextModelService,
@optional(IFileService) private _fileService: IFileService
) {
this._editor = editor;
this._model = new CodeActionModel(this._editor, markerService, contextKeyService);
this._codeActionContextMenu = new CodeActionContextMenu(editor, contextMenuService, action => this._onApplyCodeAction(action));
this._lightBulbWidget = new LightBulbWidget(editor);
this._updateLightBulbTitle();
this._disposables.push(
this._codeActionContextMenu.onDidExecuteCodeAction(_ => this._model.trigger({ type: 'auto', filter: {} })),
this._lightBulbWidget.onClick(this._handleLightBulbSelect, this),
this._model.onDidChangeFixes(e => this._onCodeActionsEvent(e)),
this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle, this)
);
}
public dispose(): void {
this._model.dispose();
dispose(this._disposables);
}
private _onCodeActionsEvent(e: CodeActionsComputeEvent): void {
if (e && e.trigger.filter && e.trigger.filter.kind) {
// Triggered for specific scope
// Apply if we only have one action or requested autoApply, otherwise show menu
e.actions.then(fixes => {
if (e.trigger.autoApply === CodeActionAutoApply.First || (e.trigger.autoApply === CodeActionAutoApply.IfSingle && fixes.length === 1)) {
this._onApplyCodeAction(fixes[0]);
} else {
this._codeActionContextMenu.show(e.actions, e.position);
}
});
return;
}
if (e && e.trigger.type === 'manual') {
this._codeActionContextMenu.show(e.actions, e.position);
} else if (e && e.actions) {
// auto magically triggered
// * update an existing list of code actions
// * manage light bulb
if (this._codeActionContextMenu.isVisible) {
this._codeActionContextMenu.show(e.actions, e.position);
} else {
this._lightBulbWidget.model = e;
}
} else {
this._lightBulbWidget.hide();
}
}
public getId(): string {
return QuickFixController.ID;
}
private _handleLightBulbSelect(coords: { x: number, y: number }): void {
this._codeActionContextMenu.show(this._lightBulbWidget.model.actions, coords);
}
public triggerFromEditorSelection(filter?: CodeActionFilter, autoApply?: CodeActionAutoApply): TPromise<CodeAction[] | undefined> {
return this._model.trigger({ type: 'manual', filter, autoApply });
}
private _updateLightBulbTitle(): void {
const kb = this._keybindingService.lookupKeybinding(QuickFixAction.Id);
let title: string;
if (kb) {
title = nls.localize('quickFixWithKb', "Show Fixes ({0})", kb.getLabel());
} else {
title = nls.localize('quickFix', "Show Fixes");
}
this._lightBulbWidget.title = title;
}
private async _onApplyCodeAction(action: CodeAction): TPromise<void> {
await applyCodeAction(action, this._textModelService, this._fileService, this._commandService, this._editor);
}
}
export async function applyCodeAction(
action: CodeAction,
textModelService: ITextModelService,
fileService: IFileService,
commandService: ICommandService,
editor: ICodeEditor,
) {
if (action.edit) {
await BulkEdit.perform(action.edit.edits, textModelService, fileService, editor);
}
if (action.command) {
await commandService.executeCommand(action.command.id, ...action.command.arguments);
}
}
function showCodeActionsForEditorSelection(
editor: ICodeEditor,
notAvailableMessage: string,
filter?: CodeActionFilter,
autoApply?: CodeActionAutoApply
) {
const controller = QuickFixController.get(editor);
if (!controller) {
return;
}
const pos = editor.getPosition();
controller.triggerFromEditorSelection(filter, autoApply).then(codeActions => {
if (!codeActions || !codeActions.length) {
MessageController.get(editor).showMessage(notAvailableMessage, pos);
}
});
}
export class QuickFixAction extends EditorAction {
static readonly Id = 'editor.action.quickFix';
constructor() {
super({
id: QuickFixAction.Id,
label: nls.localize('quickfix.trigger.label', "Quick Fix..."),
alias: 'Quick Fix',
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: KeyMod.CtrlCmd | KeyCode.US_DOT
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
return showCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"));
}
}
class CodeActionCommandArgs {
public static fromUser(arg: any): CodeActionCommandArgs {
if (!arg || typeof arg !== 'object') {
return new CodeActionCommandArgs(CodeActionKind.Empty, CodeActionAutoApply.IfSingle);
}
return new CodeActionCommandArgs(
CodeActionCommandArgs.getKindFromUser(arg),
CodeActionCommandArgs.getApplyFromUser(arg));
}
private static getApplyFromUser(arg: any) {
switch (typeof arg.apply === 'string' ? arg.apply.toLowerCase() : '') {
case 'first':
return CodeActionAutoApply.First;
case 'never':
return CodeActionAutoApply.Never;
case 'ifsingle':
default:
return CodeActionAutoApply.IfSingle;
}
}
private static getKindFromUser(arg: any) {
return typeof arg.kind === 'string'
? new CodeActionKind(arg.kind)
: CodeActionKind.Empty;
}
private constructor(
public readonly kind: CodeActionKind,
public readonly apply: CodeActionAutoApply
) { }
}
export class CodeActionCommand extends EditorCommand {
static readonly Id = 'editor.action.codeAction';
constructor() {
super({
id: CodeActionCommand.Id,
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider)
});
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, userArg: any) {
const args = CodeActionCommandArgs.fromUser(userArg);
return showCodeActionsForEditorSelection(editor, nls.localize('editor.action.quickFix.noneMessage', "No code actions available"), { kind: args.kind, includeSourceActions: true }, args.apply);
}
}
export class RefactorAction extends EditorAction {
static readonly Id = 'editor.action.refactor';
constructor() {
super({
id: RefactorAction.Id,
label: nls.localize('refactor.label', "Refactor..."),
alias: 'Refactor',
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_R,
mac: {
primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_R
}
},
menuOpts: {
group: '1_modification',
order: 2,
when: ContextKeyExpr.and(
EditorContextKeys.writable,
contextKeyForSupportedActions(CodeActionKind.Refactor)),
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
return showCodeActionsForEditorSelection(editor,
nls.localize('editor.action.refactor.noneMessage', "No refactorings available"),
{ kind: CodeActionKind.Refactor },
CodeActionAutoApply.Never);
}
}
export class SourceAction extends EditorAction {
static readonly Id = 'editor.action.sourceAction';
constructor() {
super({
id: SourceAction.Id,
label: nls.localize('source.label', "Source Action..."),
alias: 'Source Action',
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
menuOpts: {
group: '1_modification',
order: 2.1,
when: ContextKeyExpr.and(
EditorContextKeys.writable,
contextKeyForSupportedActions(CodeActionKind.Source)),
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
return showCodeActionsForEditorSelection(editor,
nls.localize('editor.action.source.noneMessage', "No source actions available"),
{ kind: CodeActionKind.Source, includeSourceActions: true },
CodeActionAutoApply.Never);
}
}
export class OrganizeImportsAction extends EditorAction {
static readonly Id = 'editor.action.organizeImports';
constructor() {
super({
id: OrganizeImportsAction.Id,
label: nls.localize('organizeImports.label', "Organize Imports"),
alias: 'Organize Imports',
precondition: ContextKeyExpr.and(
EditorContextKeys.writable,
contextKeyForSupportedActions(CodeActionKind.SourceOrganizeImports)),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_O
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
return showCodeActionsForEditorSelection(editor,
nls.localize('editor.action.organize.noneMessage', "No organize imports action available"),
{ kind: CodeActionKind.SourceOrganizeImports, includeSourceActions: true },
CodeActionAutoApply.IfSingle);
}
}