Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable code actions and workspace edits for the scm input #176699

Merged
merged 1 commit into from
Mar 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class QuickFixAction extends EditorAction {
alias: 'Quick Fix...',
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
kbExpr: EditorContextKeys.textInputFocus,
primary: KeyMod.CtrlCmd | KeyCode.Period,
weight: KeybindingWeight.EditorContrib
}
Expand Down Expand Up @@ -129,7 +129,7 @@ export class RefactorAction extends EditorAction {
alias: 'Refactor...',
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasCodeActionsProvider),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
kbExpr: EditorContextKeys.textInputFocus,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyR,
mac: {
primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KeyR
Expand Down Expand Up @@ -226,7 +226,7 @@ export class OrganizeImportsAction extends EditorAction {
EditorContextKeys.writable,
contextKeyForSupportedActions(CodeActionKind.SourceOrganizeImports)),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
kbExpr: EditorContextKeys.textInputFocus,
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KeyO,
weight: KeybindingWeight.EditorContrib
},
Expand Down Expand Up @@ -273,7 +273,7 @@ export class AutoFixAction extends EditorAction {
EditorContextKeys.writable,
contextKeyForSupportedActions(CodeActionKind.QuickFix)),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
kbExpr: EditorContextKeys.textInputFocus,
primary: KeyMod.Alt | KeyMod.Shift | KeyCode.Period,
mac: {
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Period
Expand Down
60 changes: 48 additions & 12 deletions src/vs/workbench/contrib/scm/browser/scmViewPane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import 'vs/css!./media/scm';
import { Event, Emitter } from 'vs/base/common/event';
import { basename, dirname } from 'vs/base/common/resources';
import { IDisposable, Disposable, DisposableStore, combinedDisposable, dispose, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, Disposable, DisposableStore, combinedDisposable, dispose, toDisposable, MutableDisposable, IReference } from 'vs/base/common/lifecycle';
import { ViewPane, IViewPaneOptions, ViewAction } from 'vs/workbench/browser/parts/views/viewPane';
import { append, $, Dimension, asCSSUrl, trackFocus, clearNode } from 'vs/base/browser/dom';
import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
Expand Down Expand Up @@ -90,6 +90,8 @@ import { MessageController } from 'vs/editor/contrib/message/browser/messageCont
import { contrastBorder, registerColor } from 'vs/platform/theme/common/colorRegistry';
import { defaultButtonStyles, defaultCountBadgeStyles } from 'vs/platform/theme/browser/defaultStyles';
import { GhostTextController } from 'vs/editor/contrib/inlineCompletions/browser/ghostTextController';
import { CodeActionController } from 'vs/editor/contrib/codeAction/browser/codeActionController';
import { IResolvedTextEditorModel, ITextModelContentProvider, ITextModelService } from 'vs/editor/common/services/resolverService';

type TreeElement = ISCMRepository | ISCMInput | ISCMActionButton | ISCMResourceGroup | IResourceNode<ISCMResource, ISCMResourceGroup> | ISCMResource;

Expand Down Expand Up @@ -205,7 +207,7 @@ class InputRenderer implements ICompressibleTreeRenderer<ISCMInput, FuzzyScore,

renderElement(node: ITreeNode<ISCMInput, FuzzyScore>, index: number, templateData: InputTemplate): void {
const input = node.element;
templateData.inputWidget.input = input;
templateData.inputWidget.setInput(input);

// Remember widget
this.inputWidgets.set(input, templateData.inputWidget);
Expand Down Expand Up @@ -1722,7 +1724,7 @@ class SCMInputWidget {
private inputEditor: CodeEditorWidget;
private disposables = new DisposableStore();

private model: { readonly input: ISCMInput; readonly textModel: ITextModel } | undefined;
private model: { readonly input: ISCMInput; textModelRef?: IReference<IResolvedTextEditorModel> } | undefined;
private repositoryIdContextKey: IContextKey<string | undefined>;
private repositoryDisposables = new DisposableStore();

Expand All @@ -1738,11 +1740,11 @@ class SCMInputWidget {

readonly onDidChangeContentHeight: Event<void>;

get input(): ISCMInput | undefined {
private get input(): ISCMInput | undefined {
return this.model?.input;
}

set input(input: ISCMInput | undefined) {
public async setInput(input: ISCMInput | undefined) {
if (input === this.input) {
return;
}
Expand All @@ -1755,7 +1757,7 @@ class SCMInputWidget {
this.repositoryIdContextKey.set(input?.repository.id);

if (!input) {
this.model?.textModel.dispose();
this.model?.textModelRef?.dispose();
this.inputEditor.setModel(undefined);
this.model = undefined;
return;
Expand All @@ -1777,7 +1779,21 @@ class SCMInputWidget {
this.configurationService.updateValue('editor.wordBasedSuggestions', false, { resource: uri }, ConfigurationTarget.MEMORY);
}

const textModel = this.modelService.getModel(uri) ?? this.modelService.createModel('', this.languageService.createById('scminput'), uri);
const modelValue: typeof this.model = { input, textModelRef: undefined };

// Save model
this.model = modelValue;

const modelRef = await this.textModelService.createModelReference(uri);
// Model has been changed in the meantime
if (this.model !== modelValue) {
modelRef.dispose();
return;
}

modelValue.textModelRef = modelRef;

const textModel = modelRef.object.textEditorModel;
this.inputEditor.setModel(textModel);

// Validation
Expand Down Expand Up @@ -1866,9 +1882,6 @@ class SCMInputWidget {
};
this.repositoryDisposables.add(input.onDidChangeEnablement(enabled => updateEnablement(enabled)));
updateEnablement(input.enabled);

// Save model
this.model = { input, textModel };
}

get selections(): Selection[] | null {
Expand Down Expand Up @@ -1904,7 +1917,7 @@ class SCMInputWidget {
overflowWidgetsDomNode: HTMLElement,
@IContextKeyService contextKeyService: IContextKeyService,
@IModelService private modelService: IModelService,
@ILanguageService private languageService: ILanguageService,
@ITextModelService private textModelService: ITextModelService,
@IKeybindingService private keybindingService: IKeybindingService,
@IConfigurationService private configurationService: IConfigurationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
Expand Down Expand Up @@ -1963,6 +1976,7 @@ class SCMInputWidget {
SnippetController2.ID,
SuggestController.ID,
GhostTextController.ID,
CodeActionController.ID,
])
};

Expand Down Expand Up @@ -2181,7 +2195,7 @@ class SCMInputWidget {
}

dispose(): void {
this.input = undefined;
this.setInput(undefined);
this.repositoryDisposables.dispose();
this.clearValidation();
this.disposables.dispose();
Expand Down Expand Up @@ -2228,6 +2242,8 @@ export class SCMViewPane extends ViewPane {
onDidChange: this._onDidLayout.event
};

this._register(this.instantiationService.createInstance(ScmInputContentProvider));

this._register(Event.any(this.scmService.onDidAddRepository, this.scmService.onDidRemoveRepository)(() => this._onDidChangeViewWelcomeState.fire()));
}

Expand Down Expand Up @@ -2586,3 +2602,23 @@ export class SCMActionButton implements IDisposable {
}
}
}

class ScmInputContentProvider extends Disposable implements ITextModelContentProvider {

constructor(
@ITextModelService textModelService: ITextModelService,
@IModelService private readonly _modelService: IModelService,
@ILanguageService private readonly _languageService: ILanguageService,
) {
super();
this._register(textModelService.registerTextModelContentProvider(Schemas.vscodeSourceControl, this));
}

async provideTextContent(resource: URI): Promise<ITextModel | null> {
const existing = this._modelService.getModel(resource);
if (existing) {
return existing;
}
return this._modelService.createModel('', this._languageService.createById('scminput'), resource);
}
}