Merge branch 'master' into aeschli/ts-sem
This commit is contained in:
commit
a9b2eb97de
18 changed files with 206 additions and 119 deletions
|
@ -6,16 +6,16 @@
|
|||
import { equals, flatten, isNonEmptyArray, mergeSort } from 'vs/base/common/arrays';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { illegalArgument, isPromiseCanceledError, onUnexpectedExternalError } from 'vs/base/common/errors';
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { TextModelCancellationTokenSource } from 'vs/editor/browser/core/editorState';
|
||||
import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { CodeAction, CodeActionContext, CodeActionProviderRegistry, CodeActionTrigger as CodeActionTriggerKind } from 'vs/editor/common/modes';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { CodeActionFilter, CodeActionKind, CodeActionTrigger, filtersAction, mayIncludeActionsOfKind } from './types';
|
||||
import { TextModelCancellationTokenSource } from 'vs/editor/browser/core/editorState';
|
||||
import { DisposableStore, IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { CodeActionFilter, CodeActionKind, CodeActionTrigger, CodeActionTriggerType, filtersAction, mayIncludeActionsOfKind } from './types';
|
||||
|
||||
export const codeActionCommandId = 'editor.action.codeAction';
|
||||
export const refactorCommandId = 'editor.action.refactor';
|
||||
|
@ -24,14 +24,14 @@ export const organizeImportsCommandId = 'editor.action.organizeImports';
|
|||
export const fixAllCommandId = 'editor.action.fixAll';
|
||||
|
||||
export interface CodeActionSet extends IDisposable {
|
||||
readonly validActions: readonly CodeAction[];
|
||||
readonly allActions: readonly CodeAction[];
|
||||
readonly validActions: readonly modes.CodeAction[];
|
||||
readonly allActions: readonly modes.CodeAction[];
|
||||
readonly hasAutoFix: boolean;
|
||||
}
|
||||
|
||||
class ManagedCodeActionSet extends Disposable implements CodeActionSet {
|
||||
|
||||
private static codeActionsComparator(a: CodeAction, b: CodeAction): number {
|
||||
private static codeActionsComparator(a: modes.CodeAction, b: modes.CodeAction): number {
|
||||
if (isNonEmptyArray(a.diagnostics)) {
|
||||
if (isNonEmptyArray(b.diagnostics)) {
|
||||
return a.diagnostics[0].message.localeCompare(b.diagnostics[0].message);
|
||||
|
@ -45,10 +45,10 @@ class ManagedCodeActionSet extends Disposable implements CodeActionSet {
|
|||
}
|
||||
}
|
||||
|
||||
public readonly validActions: readonly CodeAction[];
|
||||
public readonly allActions: readonly CodeAction[];
|
||||
public readonly validActions: readonly modes.CodeAction[];
|
||||
public readonly allActions: readonly modes.CodeAction[];
|
||||
|
||||
public constructor(actions: readonly CodeAction[], disposables: DisposableStore) {
|
||||
public constructor(actions: readonly modes.CodeAction[], disposables: DisposableStore) {
|
||||
super();
|
||||
this._register(disposables);
|
||||
this.allActions = mergeSort([...actions], ManagedCodeActionSet.codeActionsComparator);
|
||||
|
@ -68,9 +68,9 @@ export function getCodeActions(
|
|||
): Promise<CodeActionSet> {
|
||||
const filter = trigger.filter || {};
|
||||
|
||||
const codeActionContext: CodeActionContext = {
|
||||
const codeActionContext: modes.CodeActionContext = {
|
||||
only: filter.include?.value,
|
||||
trigger: trigger.type === 'manual' ? CodeActionTriggerKind.Manual : CodeActionTriggerKind.Automatic
|
||||
trigger: trigger.type === CodeActionTriggerType.Manual ? modes.CodeActionTrigger.Manual : modes.CodeActionTrigger.Automatic
|
||||
};
|
||||
|
||||
const cts = new TextModelCancellationTokenSource(model, token);
|
||||
|
@ -94,8 +94,8 @@ export function getCodeActions(
|
|||
}
|
||||
});
|
||||
|
||||
const listener = CodeActionProviderRegistry.onDidChange(() => {
|
||||
const newProviders = CodeActionProviderRegistry.all(model);
|
||||
const listener = modes.CodeActionProviderRegistry.onDidChange(() => {
|
||||
const newProviders = modes.CodeActionProviderRegistry.all(model);
|
||||
if (!equals(newProviders, providers)) {
|
||||
cts.cancel();
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ function getCodeActionProviders(
|
|||
model: ITextModel,
|
||||
filter: CodeActionFilter
|
||||
) {
|
||||
return CodeActionProviderRegistry.all(model)
|
||||
return modes.CodeActionProviderRegistry.all(model)
|
||||
// Don't include providers that we know will not return code actions of interest
|
||||
.filter(provider => {
|
||||
if (!provider.providedCodeActionKinds) {
|
||||
|
@ -125,7 +125,7 @@ function getCodeActionProviders(
|
|||
});
|
||||
}
|
||||
|
||||
registerLanguageCommand('_executeCodeActionProvider', async function (accessor, args): Promise<ReadonlyArray<CodeAction>> {
|
||||
registerLanguageCommand('_executeCodeActionProvider', async function (accessor, args): Promise<ReadonlyArray<modes.CodeAction>> {
|
||||
const { resource, rangeOrSelection, kind } = args;
|
||||
if (!(resource instanceof URI)) {
|
||||
throw illegalArgument();
|
||||
|
@ -149,7 +149,7 @@ registerLanguageCommand('_executeCodeActionProvider', async function (accessor,
|
|||
const codeActionSet = await getCodeActions(
|
||||
model,
|
||||
validatedRangeOrSelection,
|
||||
{ type: 'manual', filter: { includeSourceActions: true, include: kind && kind.value ? new CodeActionKind(kind.value) : undefined } },
|
||||
{ type: CodeActionTriggerType.Manual, filter: { includeSourceActions: true, include: kind && kind.value ? new CodeActionKind(kind.value) : undefined } },
|
||||
CancellationToken.None);
|
||||
|
||||
setTimeout(() => codeActionSet.dispose(), 100);
|
||||
|
|
|
@ -16,21 +16,20 @@ import { IPosition } from 'vs/editor/common/core/position';
|
|||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { CodeAction } from 'vs/editor/common/modes';
|
||||
import { CodeActionSet, refactorCommandId, sourceActionCommandId, codeActionCommandId, organizeImportsCommandId, fixAllCommandId } from 'vs/editor/contrib/codeAction/codeAction';
|
||||
import { codeActionCommandId, CodeActionSet, fixAllCommandId, organizeImportsCommandId, refactorCommandId, sourceActionCommandId } from 'vs/editor/contrib/codeAction/codeAction';
|
||||
import { CodeActionUi } from 'vs/editor/contrib/codeAction/codeActionUi';
|
||||
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 { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IMarkerService } from 'vs/platform/markers/common/markers';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { CodeActionModel, CodeActionsState, SUPPORTED_CODE_ACTIONS } from './codeActionModel';
|
||||
import { CodeActionAutoApply, CodeActionFilter, CodeActionKind, CodeActionTrigger, CodeActionCommandArgs } from './types';
|
||||
import { CodeActionAutoApply, CodeActionCommandArgs, CodeActionFilter, CodeActionKind, CodeActionTrigger, CodeActionTriggerType } from './types';
|
||||
|
||||
function contextKeyForSupportedActions(kind: CodeActionKind) {
|
||||
return ContextKeyExpr.regex(
|
||||
|
@ -83,10 +82,6 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
|||
@IMarkerService markerService: IMarkerService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IEditorProgressService progressService: IEditorProgressService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) {
|
||||
super();
|
||||
|
@ -102,7 +97,7 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
|||
await this._applyCodeAction(action);
|
||||
} finally {
|
||||
if (retrigger) {
|
||||
this._trigger({ type: 'auto', filter: {} });
|
||||
this._trigger({ type: CodeActionTriggerType.Auto, filter: {} });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +124,7 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
|||
|
||||
MessageController.get(this._editor).closeMessage();
|
||||
const triggerPosition = this._editor.getPosition();
|
||||
this._trigger({ type: 'manual', filter, autoApply, context: { notAvailableMessage, position: triggerPosition } });
|
||||
this._trigger({ type: CodeActionTriggerType.Manual, filter, autoApply, context: { notAvailableMessage, position: triggerPosition } });
|
||||
}
|
||||
|
||||
private _trigger(trigger: CodeActionTrigger) {
|
||||
|
@ -137,21 +132,41 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
|||
}
|
||||
|
||||
private _applyCodeAction(action: CodeAction): Promise<void> {
|
||||
return this._instantiationService.invokeFunction(applyCodeAction, action, this._bulkEditService, this._commandService, this._editor);
|
||||
return this._instantiationService.invokeFunction(applyCodeAction, action, this._editor);
|
||||
}
|
||||
}
|
||||
|
||||
export async function applyCodeAction(
|
||||
accessor: ServicesAccessor,
|
||||
action: CodeAction,
|
||||
bulkEditService: IBulkEditService,
|
||||
commandService: ICommandService,
|
||||
editor?: ICodeEditor,
|
||||
): Promise<void> {
|
||||
const bulkEditService = accessor.get(IBulkEditService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const telemetryService = accessor.get(ITelemetryService);
|
||||
const notificationService = accessor.get(INotificationService);
|
||||
|
||||
type ApplyCodeActionEvent = {
|
||||
codeActionTitle: string;
|
||||
codeActionKind: string | undefined;
|
||||
codeActionIsPreferred: boolean;
|
||||
};
|
||||
type ApplyCodeEventClassification = {
|
||||
codeActionTitle: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
codeActionKind: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
codeActionIsPreferred: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
};
|
||||
|
||||
telemetryService.publicLog2<ApplyCodeActionEvent, ApplyCodeEventClassification>('codeAction.applyCodeAction', {
|
||||
codeActionTitle: action.title,
|
||||
codeActionKind: action.kind,
|
||||
codeActionIsPreferred: !!action.isPreferred,
|
||||
});
|
||||
|
||||
if (action.edit) {
|
||||
await bulkEditService.apply(action.edit, { editor });
|
||||
}
|
||||
|
||||
if (action.command) {
|
||||
try {
|
||||
await commandService.executeCommand(action.command.id, ...(action.command.arguments || []));
|
||||
|
@ -161,7 +176,6 @@ export async function applyCodeAction(
|
|||
typeof message === 'string'
|
||||
? message
|
||||
: nls.localize('applyCodeActionFailed', "An unknown error occurred while applying the code action"));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/cont
|
|||
import { IMarkerService } from 'vs/platform/markers/common/markers';
|
||||
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { getCodeActions, CodeActionSet } from './codeAction';
|
||||
import { CodeActionTrigger } from './types';
|
||||
import { CodeActionTrigger, CodeActionTriggerType } from './types';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
|
||||
|
@ -56,14 +56,14 @@ class CodeActionOracle extends Disposable {
|
|||
|
||||
if (resources.some(resource => isEqual(resource, model.uri))) {
|
||||
this._autoTriggerTimer.cancelAndSet(() => {
|
||||
this.trigger({ type: 'auto' });
|
||||
this.trigger({ type: CodeActionTriggerType.Auto });
|
||||
}, this._delay);
|
||||
}
|
||||
}
|
||||
|
||||
private _onCursorChange(): void {
|
||||
this._autoTriggerTimer.cancelAndSet(() => {
|
||||
this.trigger({ type: 'auto' });
|
||||
this.trigger({ type: CodeActionTriggerType.Auto });
|
||||
}, this._delay);
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ class CodeActionOracle extends Disposable {
|
|||
}
|
||||
const model = this._editor.getModel();
|
||||
const selection = this._editor.getSelection();
|
||||
if (selection.isEmpty() && trigger.type === 'auto') {
|
||||
if (selection.isEmpty() && trigger.type === CodeActionTriggerType.Auto) {
|
||||
const { lineNumber, column } = selection.getPosition();
|
||||
const line = model.getLineContent(lineNumber);
|
||||
if (line.length === 0) {
|
||||
|
@ -214,14 +214,14 @@ export class CodeActionModel extends Disposable {
|
|||
}
|
||||
|
||||
const actions = createCancelablePromise(token => getCodeActions(model, trigger.selection, trigger.trigger, token));
|
||||
if (this._progressService && trigger.trigger.type === 'manual') {
|
||||
if (this._progressService && trigger.trigger.type === CodeActionTriggerType.Manual) {
|
||||
this._progressService.showWhile(actions, 250);
|
||||
}
|
||||
|
||||
this.setState(new CodeActionsState.Triggered(trigger.trigger, trigger.selection, trigger.position, actions));
|
||||
|
||||
}, undefined);
|
||||
this._codeActionOracle.value.trigger({ type: 'auto' });
|
||||
this._codeActionOracle.value.trigger({ type: CodeActionTriggerType.Auto });
|
||||
} else {
|
||||
this._supportedCodeActions.reset();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import { MessageController } from 'vs/editor/contrib/message/messageController';
|
|||
import { CodeActionsState } from './codeActionModel';
|
||||
import { CodeActionMenu, CodeActionShowOptions } from './codeActionMenu';
|
||||
import { LightBulbWidget } from './lightBulbWidget';
|
||||
import { CodeActionAutoApply, CodeActionTrigger } from './types';
|
||||
import { CodeActionAutoApply, CodeActionTrigger, CodeActionTriggerType } from './types';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export class CodeActionUi extends Disposable {
|
||||
|
@ -67,7 +67,7 @@ export class CodeActionUi extends Disposable {
|
|||
|
||||
this._lightBulbWidget.getValue().update(actions, newState.position);
|
||||
|
||||
if (newState.trigger.type === 'manual') {
|
||||
if (newState.trigger.type === CodeActionTriggerType.Manual) {
|
||||
if (newState.trigger.filter?.include) { // Triggered for specific scope
|
||||
// Check to see if we want to auto apply.
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Range } from 'vs/editor/common/core/range';
|
|||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
|
||||
import { CodeActionKind } from 'vs/editor/contrib/codeAction/types';
|
||||
import { CodeActionKind, CodeActionTriggerType } from 'vs/editor/contrib/codeAction/types';
|
||||
import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
|
@ -125,7 +125,7 @@ suite('CodeAction', () => {
|
|||
testData.tsLint.abc
|
||||
];
|
||||
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'manual' }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: CodeActionTriggerType.Manual }, CancellationToken.None);
|
||||
assert.equal(actions.length, 6);
|
||||
assert.deepEqual(actions, expected);
|
||||
});
|
||||
|
@ -140,20 +140,20 @@ suite('CodeAction', () => {
|
|||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'auto', filter: { include: new CodeActionKind('a') } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a') } }, CancellationToken.None);
|
||||
assert.equal(actions.length, 2);
|
||||
assert.strictEqual(actions[0].title, 'a');
|
||||
assert.strictEqual(actions[1].title, 'a.b');
|
||||
}
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'auto', filter: { include: new CodeActionKind('a.b') } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a.b') } }, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'a.b');
|
||||
}
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'auto', filter: { include: new CodeActionKind('a.b.c') } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a.b.c') } }, CancellationToken.None);
|
||||
assert.equal(actions.length, 0);
|
||||
}
|
||||
});
|
||||
|
@ -172,7 +172,7 @@ suite('CodeAction', () => {
|
|||
|
||||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'auto', filter: { include: new CodeActionKind('a') } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: CodeActionTriggerType.Auto, filter: { include: new CodeActionKind('a') } }, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'a');
|
||||
});
|
||||
|
@ -186,13 +186,13 @@ suite('CodeAction', () => {
|
|||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'auto' }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: CodeActionTriggerType.Auto }, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'b');
|
||||
}
|
||||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: 'auto', filter: { include: CodeActionKind.Source, includeSourceActions: true } }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), { type: CodeActionTriggerType.Auto, filter: { include: CodeActionKind.Source, includeSourceActions: true } }, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
assert.strictEqual(actions[0].title, 'a');
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ suite('CodeAction', () => {
|
|||
|
||||
{
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), {
|
||||
type: 'auto', filter: {
|
||||
type: CodeActionTriggerType.Auto, filter: {
|
||||
include: CodeActionKind.Source.append('test'),
|
||||
excludes: [CodeActionKind.Source],
|
||||
includeSourceActions: true,
|
||||
|
@ -234,7 +234,7 @@ suite('CodeAction', () => {
|
|||
disposables.add(modes.CodeActionProviderRegistry.register('fooLang', provider));
|
||||
|
||||
const { validActions: actions } = await getCodeActions(model, new Range(1, 1, 2, 1), {
|
||||
type: 'auto',
|
||||
type: CodeActionTriggerType.Auto,
|
||||
filter: {
|
||||
include: CodeActionKind.QuickFix
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import { CodeActionModel, CodeActionsState } from 'vs/editor/contrib/codeAction/
|
|||
import { createTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
|
||||
import { MarkerService } from 'vs/platform/markers/common/markerService';
|
||||
import { CodeActionTriggerType } from 'vs/editor/contrib/codeAction/types';
|
||||
|
||||
const testProvider = {
|
||||
provideCodeActions(): modes.CodeActionList {
|
||||
|
@ -59,7 +60,7 @@ suite('CodeActionModel', () => {
|
|||
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
|
||||
assertType(e.type === CodeActionsState.Type.Triggered);
|
||||
|
||||
assert.strictEqual(e.trigger.type, 'auto');
|
||||
assert.strictEqual(e.trigger.type, CodeActionTriggerType.Auto);
|
||||
assert.ok(e.actions);
|
||||
|
||||
e.actions.then(fixes => {
|
||||
|
@ -100,7 +101,7 @@ suite('CodeActionModel', () => {
|
|||
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
|
||||
assertType(e.type === CodeActionsState.Type.Triggered);
|
||||
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
assert.equal(e.trigger.type, CodeActionTriggerType.Auto);
|
||||
assert.ok(e.actions);
|
||||
e.actions.then(fixes => {
|
||||
model.dispose();
|
||||
|
@ -138,7 +139,7 @@ suite('CodeActionModel', () => {
|
|||
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
|
||||
assertType(e.type === CodeActionsState.Type.Triggered);
|
||||
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
assert.equal(e.trigger.type, CodeActionTriggerType.Auto);
|
||||
const selection = <Selection>e.rangeOrSelection;
|
||||
assert.deepEqual(selection.selectionStartLineNumber, 1);
|
||||
assert.deepEqual(selection.selectionStartColumn, 1);
|
||||
|
@ -163,7 +164,7 @@ suite('CodeActionModel', () => {
|
|||
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
|
||||
assertType(e.type === CodeActionsState.Type.Triggered);
|
||||
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
assert.equal(e.trigger.type, CodeActionTriggerType.Auto);
|
||||
++triggerCount;
|
||||
|
||||
// give time for second trigger before completing test
|
||||
|
|
|
@ -102,8 +102,13 @@ export function filtersAction(filter: CodeActionFilter, action: CodeAction): boo
|
|||
return true;
|
||||
}
|
||||
|
||||
export const enum CodeActionTriggerType {
|
||||
Auto,
|
||||
Manual
|
||||
}
|
||||
|
||||
export interface CodeActionTrigger {
|
||||
readonly type: 'auto' | 'manual';
|
||||
readonly type: CodeActionTriggerType;
|
||||
readonly filter?: CodeActionFilter;
|
||||
readonly autoApply?: CodeActionAutoApply;
|
||||
readonly context?: {
|
||||
|
|
|
@ -34,7 +34,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
|||
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||
import { getCodeActions, CodeActionSet } from 'vs/editor/contrib/codeAction/codeAction';
|
||||
import { QuickFixAction, QuickFixController } from 'vs/editor/contrib/codeAction/codeActionCommands';
|
||||
import { CodeActionKind } from 'vs/editor/contrib/codeAction/types';
|
||||
import { CodeActionKind, CodeActionTriggerType } from 'vs/editor/contrib/codeAction/types';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
|
@ -592,7 +592,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
|||
return getCodeActions(
|
||||
this._editor.getModel()!,
|
||||
new Range(marker.startLineNumber, marker.startColumn, marker.endLineNumber, marker.endColumn),
|
||||
{ type: 'manual', filter: { include: CodeActionKind.QuickFix } },
|
||||
{ type: CodeActionTriggerType.Manual, filter: { include: CodeActionKind.QuickFix } },
|
||||
cancellationToken);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import { IdleValue } from 'vs/base/common/async';
|
|||
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { trimTrailingWhitespace } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand';
|
||||
import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
|
@ -19,11 +18,11 @@ import { CodeAction } from 'vs/editor/common/modes';
|
|||
import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
|
||||
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
|
||||
import { applyCodeAction } from 'vs/editor/contrib/codeAction/codeActionCommands';
|
||||
import { CodeActionKind } from 'vs/editor/contrib/codeAction/types';
|
||||
import { CodeActionKind, CodeActionTriggerType } from 'vs/editor/contrib/codeAction/types';
|
||||
import { formatDocumentWithSelectedProvider, FormattingMode } from 'vs/editor/contrib/format/format';
|
||||
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
@ -247,8 +246,6 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
|
|||
class CodeActionOnSaveParticipant implements ISaveParticipantParticipant {
|
||||
|
||||
constructor(
|
||||
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) { }
|
||||
|
@ -308,13 +305,13 @@ class CodeActionOnSaveParticipant implements ISaveParticipantParticipant {
|
|||
|
||||
private async applyCodeActions(actionsToRun: readonly CodeAction[]) {
|
||||
for (const action of actionsToRun) {
|
||||
await this._instantiationService.invokeFunction(applyCodeAction, action, this._bulkEditService, this._commandService);
|
||||
await this._instantiationService.invokeFunction(applyCodeAction, action);
|
||||
}
|
||||
}
|
||||
|
||||
private getActionsToRun(model: ITextModel, codeActionKind: CodeActionKind, excludes: readonly CodeActionKind[], token: CancellationToken) {
|
||||
return getCodeActions(model, model.getFullModelRange(), {
|
||||
type: 'auto',
|
||||
type: CodeActionTriggerType.Auto,
|
||||
filter: { include: codeActionKind, excludes: excludes, includeSourceActions: true },
|
||||
}, token);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
|||
import { URI } from 'vs/base/common/uri';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { EditorMemento } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { EditorActivation, IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
|
@ -182,7 +182,8 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditor {
|
|||
options = EditorOptions.create(preservingOptions);
|
||||
}
|
||||
|
||||
this.editorService.openEditor(binaryDiffInput, options, this.group);
|
||||
// Replace this editor with the binary one
|
||||
this.editorService.replaceEditors([{ editor: input, replacement: binaryDiffInput, options }], this.group || ACTIVE_GROUP);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ export class DiffEditorInput extends SideBySideEditorInput {
|
|||
if (!super.matches(otherInput)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return otherInput instanceof DiffEditorInput && otherInput.forceOpenAsBinary === this.forceOpenAsBinary;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ export class CodeActionDocumentationContribution extends Disposable implements I
|
|||
}
|
||||
|
||||
async provideCodeActions(_model: ITextModel, _range: Range | Selection, context: CodeActionContext, _token: CancellationToken): Promise<CodeActionList> {
|
||||
if (!context.only || !CodeActionKind.Refactor.contains(new CodeActionKind(context.only))) {
|
||||
if (CodeActionKind.Refactor.value !== context.only) {
|
||||
return {
|
||||
actions: [],
|
||||
dispose: () => { }
|
||||
|
|
|
@ -347,9 +347,15 @@ export class CustomEditorContribution implements IWorkbenchContribution {
|
|||
options: ITextEditorOptions | undefined,
|
||||
group: IEditorGroup
|
||||
): IOpenEditorOverride | undefined {
|
||||
const userConfiguredEditors = this.customEditorService.getUserConfiguredCustomEditors(resource);
|
||||
const contributedEditors = this.customEditorService.getContributedCustomEditors(resource);
|
||||
if (!userConfiguredEditors.length && !contributedEditors.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if there already an editor for the resource in the group.
|
||||
// If there is, we want to open that instead of creating a new editor.
|
||||
// This ensures that we preserve whatever state the editor was previously in
|
||||
// This ensures that we preserve whatever type of editor was previously being used
|
||||
// when the user switches back to it.
|
||||
const existingEditorForResource = group.editors.find(editor => isEqual(resource, editor.getResource()));
|
||||
if (existingEditorForResource) {
|
||||
|
@ -358,14 +364,12 @@ export class CustomEditorContribution implements IWorkbenchContribution {
|
|||
};
|
||||
}
|
||||
|
||||
const userConfiguredEditors = this.customEditorService.getUserConfiguredCustomEditors(resource);
|
||||
if (userConfiguredEditors.length) {
|
||||
return {
|
||||
override: this.customEditorService.openWith(resource, userConfiguredEditors.allEditors[0].id, options, group),
|
||||
};
|
||||
}
|
||||
|
||||
const contributedEditors = this.customEditorService.getContributedCustomEditors(resource);
|
||||
if (!contributedEditors.length) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -37,10 +37,8 @@ import { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/com
|
|||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { getCodeActions, CodeActionSet } from 'vs/editor/contrib/codeAction/codeAction';
|
||||
import { CodeActionKind } from 'vs/editor/contrib/codeAction/types';
|
||||
import { CodeActionKind, CodeActionTriggerType } from 'vs/editor/contrib/codeAction/types';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { applyCodeAction } from 'vs/editor/contrib/codeAction/codeActionCommands';
|
||||
import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon';
|
||||
|
@ -489,8 +487,6 @@ export class MarkerViewModel extends Disposable {
|
|||
private readonly marker: Marker,
|
||||
@IModelService private modelService: IModelService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IBulkEditService private readonly bulkEditService: IBulkEditService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IEditorService private readonly editorService: IEditorService
|
||||
) {
|
||||
super();
|
||||
|
@ -552,7 +548,7 @@ export class MarkerViewModel extends Disposable {
|
|||
if (model) {
|
||||
if (!this.codeActionsPromise) {
|
||||
this.codeActionsPromise = createCancelablePromise(cancellationToken => {
|
||||
return getCodeActions(model, new Range(this.marker.range.startLineNumber, this.marker.range.startColumn, this.marker.range.endLineNumber, this.marker.range.endColumn), { type: 'manual', filter: { include: CodeActionKind.QuickFix } }, cancellationToken).then(actions => {
|
||||
return getCodeActions(model, new Range(this.marker.range.startLineNumber, this.marker.range.startColumn, this.marker.range.endLineNumber, this.marker.range.endColumn), { type: CodeActionTriggerType.Manual, filter: { include: CodeActionKind.QuickFix } }, cancellationToken).then(actions => {
|
||||
return this._register(actions);
|
||||
});
|
||||
});
|
||||
|
@ -571,7 +567,7 @@ export class MarkerViewModel extends Disposable {
|
|||
true,
|
||||
() => {
|
||||
return this.openFileAtMarker(this.marker)
|
||||
.then(() => this.instantiationService.invokeFunction(applyCodeAction, codeAction, this.bulkEditService, this.commandService));
|
||||
.then(() => this.instantiationService.invokeFunction(applyCodeAction, codeAction));
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
|||
import { assertType } from 'vs/base/common/types';
|
||||
import { SearchViewPaneContainer } from 'vs/workbench/contrib/search/browser/searchViewlet';
|
||||
import { EditorDescriptor, Extensions as EditorExtensions, IEditorRegistry } from 'vs/workbench/browser/editor';
|
||||
import { SearchEditorInput, SearchEditorInputFactory } from 'vs/workbench/contrib/search/browser/searchEditorCommands';
|
||||
import { SearchEditorInput, SearchEditorInputFactory, SearchEditorContribution } from 'vs/workbench/contrib/search/browser/searchEditorCommands';
|
||||
import { SearchEditor } from 'vs/workbench/contrib/search/browser/searchEditor';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { Extensions as EditorInputExtensions, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor';
|
||||
|
@ -909,3 +909,6 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
|||
Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory(
|
||||
SearchEditorInput.ID,
|
||||
SearchEditorInputFactory);
|
||||
|
||||
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(SearchEditorContribution, LifecyclePhase.Starting);
|
||||
|
|
|
@ -158,6 +158,8 @@ export class SearchEditor extends BaseEditor {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
this._register(this.searchResultEditor.onDidChangeModel(() => this.hideHeader()));
|
||||
}
|
||||
|
||||
private async runSearch(instant = false) {
|
||||
|
@ -225,14 +227,28 @@ export class SearchEditor extends BaseEditor {
|
|||
(assertIsDefined(this._input) as SearchEditorInput).setConfig(config);
|
||||
|
||||
const labelFormatter = (uri: URI): string => this.labelService.getUriLabel(uri, { relative: true });
|
||||
const results = serializeSearchResultForEditor(searchModel.searchResult, config.includes, config.excludes, config.contextLines, labelFormatter, false);
|
||||
const results = serializeSearchResultForEditor(searchModel.searchResult, config.includes, config.excludes, config.contextLines, labelFormatter, true);
|
||||
const textModel = assertIsDefined(this.searchResultEditor.getModel());
|
||||
textModel.setValue(results.text.join(lineDelimiter));
|
||||
this.hideHeader();
|
||||
textModel.deltaDecorations([], results.matchRanges.map(range => ({ range, options: { className: 'searchEditorFindMatch', stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges } })));
|
||||
|
||||
searchModel.dispose();
|
||||
}
|
||||
|
||||
private hideHeader() {
|
||||
const headerLines =
|
||||
this.searchResultEditor
|
||||
.getModel()
|
||||
?.getValueInRange(new Range(1, 1, 6, 1))
|
||||
.split('\n')
|
||||
.filter(line => line.startsWith('#'))
|
||||
.length
|
||||
?? 0;
|
||||
|
||||
this.searchResultEditor.setHiddenAreas([new Range(1, 1, headerLines + 1, 1)]);
|
||||
}
|
||||
|
||||
layout(dimension: DOM.Dimension) {
|
||||
this.dimension = dimension;
|
||||
this.reLayout();
|
||||
|
@ -255,8 +271,7 @@ export class SearchEditor extends BaseEditor {
|
|||
if (!(newInput instanceof SearchEditorInput)) { return; }
|
||||
this.pauseSearching = true;
|
||||
// TODO: Manage model lifecycle in SearchEditorInput
|
||||
const model = this.modelService.getModel(newInput.getResource());
|
||||
|
||||
const model = this.modelService.getModel(newInput.resource);
|
||||
this.searchResultEditor.setModel(model);
|
||||
this.queryEditorWidget.setValue(newInput.config.query, true);
|
||||
this.queryEditorWidget.searchInput.setCaseSensitive(newInput.config.caseSensitive);
|
||||
|
|
|
@ -11,7 +11,7 @@ import { URI } from 'vs/base/common/uri';
|
|||
import 'vs/css!./media/searchEditor';
|
||||
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { EndOfLinePreference, TrackedRangeStickiness } from 'vs/editor/common/model';
|
||||
import { EndOfLinePreference, TrackedRangeStickiness, ITextModel } from 'vs/editor/common/model';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
@ -25,16 +25,22 @@ import { getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/co
|
|||
import { FileMatch, Match, searchMatchComparer, SearchModel, SearchResult } from 'vs/workbench/contrib/search/common/searchModel';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IPatternInfo, ISearchConfigurationProperties, ITextQuery } from 'vs/workbench/services/search/common/search';
|
||||
import { EditorInput, IEditorInputFactory } from 'vs/workbench/common/editor';
|
||||
import { IEditorInputFactory, GroupIdentifier, EditorInput } from 'vs/workbench/common/editor';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { SearchEditor } from 'vs/workbench/contrib/search/browser/searchEditor';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ITextFileSaveOptions, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
|
||||
import type { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
// import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
|
||||
|
||||
|
||||
|
||||
export type SearchConfiguration = {
|
||||
query: string,
|
||||
includes: string,
|
||||
excludes: string,
|
||||
excludes: string
|
||||
contextLines: number,
|
||||
wholeWord: boolean,
|
||||
caseSensitive: boolean,
|
||||
|
@ -43,6 +49,27 @@ export type SearchConfiguration = {
|
|||
showIncludesExcludes: boolean,
|
||||
};
|
||||
|
||||
export class SearchEditorContribution implements IWorkbenchContribution {
|
||||
// constructor(
|
||||
// @IEditorService private readonly editorService: IEditorService,
|
||||
// @ITextFileService protected readonly textFileService: ITextFileService,
|
||||
// ) {
|
||||
// this.editorService.overrideOpenEditor(async (editor, options, group) => {
|
||||
// const resource = editor.getResource();
|
||||
// if (!resource || !endsWith(resource.path, '.code-search') || !(editor instanceof FileEditorInput)) {
|
||||
// return undefined;
|
||||
// }
|
||||
|
||||
// console.log('hello agian');
|
||||
// const contents = await this.textFileService.read(resource);
|
||||
// contents.value;
|
||||
|
||||
// return undefined;
|
||||
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
export class SearchEditorInputFactory implements IEditorInputFactory {
|
||||
|
||||
canSerialize() { return true; }
|
||||
|
@ -52,7 +79,7 @@ export class SearchEditorInputFactory implements IEditorInputFactory {
|
|||
}
|
||||
|
||||
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): SearchEditorInput | undefined {
|
||||
return instantiationService.createInstance(SearchEditorInput, JSON.parse(serializedEditorInput));
|
||||
return instantiationService.createInstance(SearchEditorInput, JSON.parse(serializedEditorInput), undefined);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,40 +87,56 @@ let searchEditorInputInstances = 0;
|
|||
export class SearchEditorInput extends EditorInput {
|
||||
static readonly ID: string = 'workbench.editorinputs.searchEditorInput';
|
||||
|
||||
public config: SearchConfiguration;
|
||||
private instanceNumber: number = searchEditorInputInstances++;
|
||||
private _config: SearchConfiguration;
|
||||
public get config(): Readonly<SearchConfiguration> {
|
||||
return this._config;
|
||||
}
|
||||
|
||||
private model: ITextModel;
|
||||
public readonly resource: URI;
|
||||
|
||||
constructor(
|
||||
config: SearchConfiguration | undefined,
|
||||
initialContents: string | undefined,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IEditorService protected readonly editorService: IEditorService,
|
||||
@IEditorGroupsService protected readonly editorGroupService: IEditorGroupsService,
|
||||
@ITextFileService protected readonly textFileService: ITextFileService,
|
||||
@IUntitledTextEditorService protected readonly untitledTextEditorService: IUntitledTextEditorService,
|
||||
) {
|
||||
super();
|
||||
this.resource = URI.from({ scheme: 'search-editor', fragment: `${searchEditorInputInstances++}` });
|
||||
|
||||
|
||||
if (config === undefined) {
|
||||
this.config = { query: '', includes: '', excludes: '', contextLines: 0, wholeWord: false, caseSensitive: false, regexp: false, useIgnores: true, showIncludesExcludes: false };
|
||||
this._config = { query: '', includes: '', excludes: '', contextLines: 0, wholeWord: false, caseSensitive: false, regexp: false, useIgnores: true, showIncludesExcludes: false };
|
||||
} else {
|
||||
this.config = config;
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
const searchResultMode = this.modeService.create('search-result');
|
||||
this.modelService.createModel('', searchResultMode, this.getResource());
|
||||
|
||||
this.model = this.modelService.createModel(initialContents ?? '', searchResultMode, this.resource);
|
||||
}
|
||||
|
||||
async save(group: GroupIdentifier, options?: ITextFileSaveOptions): Promise<boolean> {
|
||||
const path = (this.config.query.replace(/\W/g, '') || 'Untitled Search') + '.code-search';
|
||||
const untitledResource = URI.from({ scheme: 'untitled', path, fragment: this.resource.fragment });
|
||||
const a = this.untitledTextEditorService.createOrGet(untitledResource, 'search-result', this.model.getValue());
|
||||
return a.save(group, options).finally(() => a.dispose());
|
||||
}
|
||||
|
||||
getTypeId(): string {
|
||||
return SearchEditorInput.ID;
|
||||
}
|
||||
|
||||
getResource(): URI {
|
||||
return URI.from({ scheme: 'search-editor', fragment: `${this.instanceNumber}` });
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return this.config.query ? localize('searchTitle.withQuery', "Search: {0}", this.config.query) : localize('searchTitle', "Search");
|
||||
}
|
||||
|
||||
setConfig(config: SearchConfiguration) {
|
||||
this.config = config;
|
||||
this._config = config;
|
||||
this._onDidChangeLabel.fire();
|
||||
}
|
||||
|
||||
|
@ -102,9 +145,17 @@ export class SearchEditorInput extends EditorInput {
|
|||
}
|
||||
|
||||
dispose() {
|
||||
this.modelService.destroyModel(this.getResource());
|
||||
this.modelService.destroyModel(this.resource);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
matches(other: unknown) {
|
||||
if (this === other) { return true; }
|
||||
if (other instanceof UntitledTextEditorInput) {
|
||||
if (other.getResource().fragment === this.resource.fragment) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Using \r\n on Windows inserts an extra newline between results.
|
||||
|
@ -313,7 +364,7 @@ export const serializeSearchResultForEditor = (searchResult: SearchResult, rawIn
|
|||
.map(folderMatch => folderMatch.matches().sort(searchMatchComparer)
|
||||
.map(fileMatch => fileMatchToSearchResultFormat(fileMatch, labelFormatter)))));
|
||||
|
||||
return { matchRanges: allResults.matchRanges.map(translateRangeLines(header.length)), text: header.concat(allResults.text) };
|
||||
return { matchRanges: allResults.matchRanges.map(translateRangeLines(header.length)), text: header.concat(allResults.text.length ? allResults.text : ['No Results']) };
|
||||
};
|
||||
|
||||
export const refreshActiveEditorSearch =
|
||||
|
@ -373,7 +424,7 @@ export const refreshActiveEditorSearch =
|
|||
await searchModel.search(query);
|
||||
|
||||
const labelFormatter = (uri: URI): string => labelService.getUriLabel(uri, { relative: true });
|
||||
const results = serializeSearchResultForEditor(searchModel.searchResult, contentPattern.includes, contentPattern.excludes, contextLines, labelFormatter, false);
|
||||
const results = serializeSearchResultForEditor(searchModel.searchResult, contentPattern.includes, contentPattern.excludes, contextLines, labelFormatter, true);
|
||||
|
||||
textModel.setValue(results.text.join(lineDelimiter));
|
||||
textModel.deltaDecorations([], results.matchRanges.map(range => ({ range, options: { className: 'searchEditorFindMatch', stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges } })));
|
||||
|
@ -381,7 +432,7 @@ export const refreshActiveEditorSearch =
|
|||
|
||||
export const openNewSearchEditor =
|
||||
async (editorService: IEditorService, instantiationService: IInstantiationService) => {
|
||||
await editorService.openEditor(instantiationService.createInstance(SearchEditorInput, undefined), { pinned: true });
|
||||
await editorService.openEditor(instantiationService.createInstance(SearchEditorInput, undefined, undefined), { pinned: true });
|
||||
};
|
||||
|
||||
export const createEditorFromSearchResult =
|
||||
|
@ -395,7 +446,7 @@ export const createEditorFromSearchResult =
|
|||
|
||||
const labelFormatter = (uri: URI): string => labelService.getUriLabel(uri, { relative: true });
|
||||
|
||||
const results = serializeSearchResultForEditor(searchResult, rawIncludePattern, rawExcludePattern, 0, labelFormatter, false);
|
||||
const results = serializeSearchResultForEditor(searchResult, rawIncludePattern, rawExcludePattern, 0, labelFormatter, true);
|
||||
const contents = results.text.join(lineDelimiter);
|
||||
let possible = {
|
||||
contents,
|
||||
|
@ -418,24 +469,22 @@ export const createEditorFromSearchResult =
|
|||
existing = editorService.getOpened(possible);
|
||||
}
|
||||
|
||||
const editor = await editorService.openEditor(
|
||||
instantiationService.createInstance(
|
||||
SearchEditorInput,
|
||||
{
|
||||
query: searchResult.query.contentPattern.pattern,
|
||||
regexp: !!searchResult.query.contentPattern.isRegExp,
|
||||
caseSensitive: !!searchResult.query.contentPattern.isCaseSensitive,
|
||||
wholeWord: !!searchResult.query.contentPattern.isWordMatch,
|
||||
includes: rawIncludePattern,
|
||||
excludes: rawExcludePattern,
|
||||
contextLines: 0,
|
||||
useIgnores: !searchResult.query.userDisabledExcludesAndIgnoreFiles,
|
||||
showIncludesExcludes: !!(rawExcludePattern || rawExcludePattern || searchResult.query.userDisabledExcludesAndIgnoreFiles)
|
||||
}),
|
||||
{ pinned: true }) as SearchEditor;
|
||||
const input = instantiationService.createInstance(
|
||||
SearchEditorInput,
|
||||
{
|
||||
query: searchResult.query.contentPattern.pattern,
|
||||
regexp: !!searchResult.query.contentPattern.isRegExp,
|
||||
caseSensitive: !!searchResult.query.contentPattern.isCaseSensitive,
|
||||
wholeWord: !!searchResult.query.contentPattern.isWordMatch,
|
||||
includes: rawIncludePattern,
|
||||
excludes: rawExcludePattern,
|
||||
contextLines: 0,
|
||||
useIgnores: !searchResult.query.userDisabledExcludesAndIgnoreFiles,
|
||||
showIncludesExcludes: !!(rawExcludePattern || rawExcludePattern || searchResult.query.userDisabledExcludesAndIgnoreFiles)
|
||||
}, contents);
|
||||
|
||||
const editor = await editorService.openEditor(input, { pinned: true }) as SearchEditor;
|
||||
const model = assertIsDefined(editor.getModel());
|
||||
model.setValue(contents);
|
||||
model.deltaDecorations([], results.matchRanges.map(range => ({ range, options: { className: 'searchEditorFindMatch', stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges } })));
|
||||
};
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ import { mock } from 'vs/workbench/test/electron-browser/api/mock';
|
|||
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { CodeActionTriggerType } from 'vs/editor/contrib/codeAction/types';
|
||||
|
||||
const defaultSelector = { scheme: 'far' };
|
||||
const model: ITextModel = EditorModel.createFromString(
|
||||
|
@ -589,7 +590,7 @@ suite('ExtHostLanguageFeatures', function () {
|
|||
}));
|
||||
|
||||
await rpcProtocol.sync();
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: CodeActionTriggerType.Manual }, CancellationToken.None);
|
||||
assert.equal(actions.length, 2);
|
||||
const [first, second] = actions;
|
||||
assert.equal(first.title, 'Testing1');
|
||||
|
@ -613,7 +614,7 @@ suite('ExtHostLanguageFeatures', function () {
|
|||
}));
|
||||
|
||||
await rpcProtocol.sync();
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: CodeActionTriggerType.Manual }, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
const [first] = actions;
|
||||
assert.equal(first.title, 'Testing1');
|
||||
|
@ -636,7 +637,7 @@ suite('ExtHostLanguageFeatures', function () {
|
|||
}));
|
||||
|
||||
await rpcProtocol.sync();
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: CodeActionTriggerType.Manual }, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
});
|
||||
|
||||
|
@ -654,7 +655,7 @@ suite('ExtHostLanguageFeatures', function () {
|
|||
}));
|
||||
|
||||
await rpcProtocol.sync();
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: 'manual' }, CancellationToken.None);
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: CodeActionTriggerType.Manual }, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue