mirror of
https://github.com/Microsoft/vscode
synced 2024-09-29 16:01:05 +00:00
Fixes #219006. Open file now opens the related file on disk, instead of just the right side.
This also applies to staged files.
This commit is contained in:
parent
701145d5e4
commit
84c007cbb2
|
@ -69,8 +69,9 @@ export class DocumentDiffItemViewModel extends Disposable {
|
|||
{ contentHeight: 500, selections: undefined, }
|
||||
);
|
||||
|
||||
public get originalUri(): URI | undefined { return this.entry.value!.original?.uri; }
|
||||
public get modifiedUri(): URI | undefined { return this.entry.value!.modified?.uri; }
|
||||
public get documentDiffItem(): IDocumentDiffItem { return this.entry.value!; }
|
||||
public get originalUri(): URI | undefined { return this.documentDiffItem.original?.uri; }
|
||||
public get modifiedUri(): URI | undefined { return this.documentDiffItem.modified?.uri; }
|
||||
|
||||
public readonly isActive: IObservable<boolean> = derived(this, reader => this._editorViewModel.activeDiffItem.read(reader) === this);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import { Dimension } from 'vs/base/browser/dom';
|
|||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { derived, derivedWithStore, observableValue, recomputeInitiallyAndOnChange } from 'vs/base/common/observable';
|
||||
import { readHotReloadableExport } from 'vs/base/common/hotReloadHelpers';
|
||||
import { IMultiDiffEditorModel } from 'vs/editor/browser/widget/multiDiffEditor/model';
|
||||
import { IDocumentDiffItem, IMultiDiffEditorModel } from 'vs/editor/browser/widget/multiDiffEditor/model';
|
||||
import { IMultiDiffEditorViewState, IMultiDiffResourceId, MultiDiffEditorWidgetImpl } from 'vs/editor/browser/widget/multiDiffEditor/multiDiffEditorWidgetImpl';
|
||||
import { MultiDiffEditorViewModel } from './multiDiffEditorViewModel';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
@ -81,6 +81,10 @@ export class MultiDiffEditorWidget extends Disposable {
|
|||
public tryGetCodeEditor(resource: URI): { diffEditor: IDiffEditor; editor: ICodeEditor } | undefined {
|
||||
return this._widgetImpl.get().tryGetCodeEditor(resource);
|
||||
}
|
||||
|
||||
public findDocumentDiffItem(resource: URI): IDocumentDiffItem | undefined {
|
||||
return this._widgetImpl.get().findDocumentDiffItem(resource);
|
||||
}
|
||||
}
|
||||
|
||||
export interface RevealOptions {
|
||||
|
|
|
@ -31,6 +31,7 @@ import { DiffEditorItemTemplate, TemplateData } from './diffEditorItemTemplate';
|
|||
import { DocumentDiffItemViewModel, MultiDiffEditorViewModel } from './multiDiffEditorViewModel';
|
||||
import { ObjectPool } from './objectPool';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IDocumentDiffItem } from 'vs/editor/browser/widget/multiDiffEditor/model';
|
||||
|
||||
export class MultiDiffEditorWidgetImpl extends Disposable {
|
||||
private readonly _scrollableElements = h('div.scrollContent', [
|
||||
|
@ -263,6 +264,14 @@ export class MultiDiffEditorWidgetImpl extends Disposable {
|
|||
});
|
||||
}
|
||||
|
||||
public findDocumentDiffItem(resource: URI): IDocumentDiffItem | undefined {
|
||||
const item = this._viewItems.get().find(v =>
|
||||
v.viewModel.diffEditorViewModel.model.modified.uri.toString() === resource.toString()
|
||||
|| v.viewModel.diffEditorViewModel.model.original.uri.toString() === resource.toString()
|
||||
);
|
||||
return item?.viewModel.documentDiffItem;
|
||||
}
|
||||
|
||||
public tryGetCodeEditor(resource: URI): { diffEditor: IDiffEditor; editor: ICodeEditor } | undefined {
|
||||
const item = this._viewItems.get().find(v =>
|
||||
v.viewModel.diffEditorViewModel.model.modified.uri.toString() === resource.toString()
|
||||
|
@ -272,6 +281,7 @@ export class MultiDiffEditorWidgetImpl extends Disposable {
|
|||
if (!editor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (item.viewModel.diffEditorViewModel.model.modified.uri.toString() === resource.toString()) {
|
||||
return { diffEditor: editor, editor: editor.getModifiedEditor() };
|
||||
} else {
|
||||
|
|
|
@ -207,11 +207,11 @@ export class MainThreadEditorTabs implements MainThreadEditorTabsShape {
|
|||
if (editor instanceof MultiDiffEditorInput) {
|
||||
const diffEditors: TextDiffInputDto[] = [];
|
||||
for (const resource of (editor?.resources.get() ?? [])) {
|
||||
if (resource.original && resource.modified) {
|
||||
if (resource.originalUri && resource.modifiedUri) {
|
||||
diffEditors.push({
|
||||
kind: TabInputKind.TextDiffInput,
|
||||
original: resource.original,
|
||||
modified: resource.modified
|
||||
original: resource.originalUri,
|
||||
modified: resource.modifiedUri
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -547,7 +547,7 @@ export interface IResourceMultiDiffEditorInput extends IBaseUntypedEditorInput {
|
|||
* The list of resources to compare.
|
||||
* If not set, the resources are dynamically derived from the {@link multiDiffSource}.
|
||||
*/
|
||||
readonly resources?: IResourceDiffEditorInput[];
|
||||
readonly resources?: IMultiDiffEditorResource[];
|
||||
|
||||
/**
|
||||
* Whether the editor should be serialized and stored for subsequent sessions.
|
||||
|
@ -555,6 +555,9 @@ export interface IResourceMultiDiffEditorInput extends IBaseUntypedEditorInput {
|
|||
readonly isTransient?: boolean;
|
||||
}
|
||||
|
||||
export interface IMultiDiffEditorResource extends IResourceDiffEditorInput {
|
||||
readonly goToFileResource?: URI;
|
||||
}
|
||||
export type IResourceMergeEditorInputSide = (IResourceEditorInput | ITextResourceEditorInput) & { detail?: string };
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,7 +36,7 @@ import { ResourceEdit } from 'vs/editor/browser/services/bulkEditService';
|
|||
import { ButtonBar } from 'vs/base/browser/ui/button/button';
|
||||
import { defaultButtonStyles } from 'vs/platform/theme/browser/defaultStyles';
|
||||
import { Mutable } from 'vs/base/common/types';
|
||||
import { IResourceDiffEditorInput } from 'vs/workbench/common/editor';
|
||||
import { IMultiDiffEditorResource, IResourceDiffEditorInput, IResourceMultiDiffEditorInput } from 'vs/workbench/common/editor';
|
||||
import { IMultiDiffEditorOptions, IMultiDiffResourceId } from 'vs/editor/browser/widget/multiDiffEditor/multiDiffEditorWidgetImpl';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { CachedFunction, LRUCachedFunction } from 'vs/base/common/cache';
|
||||
|
@ -369,16 +369,20 @@ export class BulkEditPane extends ViewPane {
|
|||
}, e.sideBySide ? SIDE_GROUP : ACTIVE_GROUP);
|
||||
}
|
||||
|
||||
private readonly _computeResourceDiffEditorInputs = new LRUCachedFunction(async (fileOperations: BulkFileOperation[]) => {
|
||||
const computeDiffEditorInput = new CachedFunction<BulkFileOperation, Promise<IResourceDiffEditorInput>>(async (fileOperation) => {
|
||||
private readonly _computeResourceDiffEditorInputs = new LRUCachedFunction<
|
||||
BulkFileOperation[],
|
||||
Promise<{ resources: IMultiDiffEditorResource[]; getResourceDiffEditorInputIdOfOperation: (operation: BulkFileOperation) => Promise<IMultiDiffResourceId> }>
|
||||
>(async (fileOperations) => {
|
||||
const computeDiffEditorInput = new CachedFunction<BulkFileOperation, Promise<IMultiDiffEditorResource>>(async (fileOperation) => {
|
||||
const fileOperationUri = fileOperation.uri;
|
||||
const previewUri = this._currentProvider!.asPreviewUri(fileOperationUri);
|
||||
// delete
|
||||
if (fileOperation.type & BulkFileOperationType.Delete) {
|
||||
return {
|
||||
original: { resource: URI.revive(previewUri) },
|
||||
modified: { resource: undefined }
|
||||
};
|
||||
modified: { resource: undefined },
|
||||
goToFileResource: fileOperation.uri,
|
||||
} satisfies IMultiDiffEditorResource;
|
||||
|
||||
}
|
||||
// rename, create, edits
|
||||
|
@ -392,8 +396,9 @@ export class BulkEditPane extends ViewPane {
|
|||
}
|
||||
return {
|
||||
original: { resource: URI.revive(leftResource) },
|
||||
modified: { resource: URI.revive(previewUri) }
|
||||
};
|
||||
modified: { resource: URI.revive(previewUri) },
|
||||
goToFileResource: leftResource,
|
||||
} satisfies IMultiDiffEditorResource;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
|||
import { localize2 } from 'vs/nls';
|
||||
import { Action2, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ITextEditorOptions, TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { resolveCommandsContext } from 'vs/workbench/browser/parts/editor/editorCommandsContext';
|
||||
import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor';
|
||||
import { MultiDiffEditor } from 'vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditor';
|
||||
import { MultiDiffEditorInput } from 'vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
@ -38,21 +38,28 @@ export class GoToFileAction extends Action2 {
|
|||
const editorService = accessor.get(IEditorService);
|
||||
const activeEditorPane = editorService.activeEditorPane;
|
||||
let selections: Selection[] | undefined = undefined;
|
||||
if (activeEditorPane instanceof MultiDiffEditor) {
|
||||
const editor = activeEditorPane.tryGetCodeEditor(uri);
|
||||
if (editor) {
|
||||
selections = editor.editor.getSelections() ?? undefined;
|
||||
}
|
||||
if (!(activeEditorPane instanceof MultiDiffEditor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = await editorService.openEditor({ resource: uri });
|
||||
if (selections && (editor instanceof TextFileEditor)) {
|
||||
const c = editor.getControl();
|
||||
if (c) {
|
||||
c.setSelections(selections);
|
||||
c.revealLineInCenter(selections[0].selectionStartLineNumber);
|
||||
}
|
||||
const editor = activeEditorPane.tryGetCodeEditor(uri);
|
||||
if (editor) {
|
||||
selections = editor.editor.getSelections() ?? undefined;
|
||||
}
|
||||
|
||||
let targetUri = uri;
|
||||
const item = activeEditorPane.findDocumentDiffItem(uri);
|
||||
if (item && item.goToFileUri) {
|
||||
targetUri = item.goToFileUri;
|
||||
}
|
||||
|
||||
await editorService.openEditor({
|
||||
resource: targetUri,
|
||||
options: {
|
||||
selection: selections?.[0],
|
||||
selectionRevealType: TextEditorSelectionRevealType.CenterIfOutsideViewport,
|
||||
} satisfies ITextEditorOptions,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import { AbstractEditorWithViewState } from 'vs/workbench/browser/parts/editor/e
|
|||
import { ICompositeControl } from 'vs/workbench/common/composite';
|
||||
import { IEditorOpenContext } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { MultiDiffEditorInput } from 'vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput';
|
||||
import { IDocumentDiffItemWithMultiDiffEditorItem, MultiDiffEditorInput } from 'vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
@ -27,6 +27,7 @@ import { IMultiDiffEditorOptions, IMultiDiffEditorViewState } from 'vs/editor/br
|
|||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IDiffEditor } from 'vs/editor/common/editorCommon';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { MultiDiffEditorItem } from 'vs/workbench/contrib/multiDiffEditor/browser/multiDiffSourceResolverService';
|
||||
|
||||
export class MultiDiffEditor extends AbstractEditorWithViewState<IMultiDiffEditorViewState> {
|
||||
static readonly ID = 'multiDiffEditor';
|
||||
|
@ -139,6 +140,13 @@ export class MultiDiffEditor extends AbstractEditorWithViewState<IMultiDiffEdito
|
|||
public tryGetCodeEditor(resource: URI): { diffEditor: IDiffEditor; editor: ICodeEditor } | undefined {
|
||||
return this._multiDiffEditorWidget!.tryGetCodeEditor(resource);
|
||||
}
|
||||
|
||||
public findDocumentDiffItem(resource: URI): MultiDiffEditorItem | undefined {
|
||||
const i = this._multiDiffEditorWidget!.findDocumentDiffItem(resource);
|
||||
if (!i) { return undefined; }
|
||||
const i2 = i as IDocumentDiffItemWithMultiDiffEditorItem;
|
||||
return i2.multiDiffEditorItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
|||
return new MultiDiffEditorItem(
|
||||
resource.original.resource,
|
||||
resource.modified.resource,
|
||||
resource.goToFileResource,
|
||||
);
|
||||
}),
|
||||
input.isTransient ?? false
|
||||
|
@ -60,6 +61,7 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
|||
data.resources?.map(resource => new MultiDiffEditorItem(
|
||||
resource.originalUri ? URI.parse(resource.originalUri) : undefined,
|
||||
resource.modifiedUri ? URI.parse(resource.modifiedUri) : undefined,
|
||||
resource.goToFileUri ? URI.parse(resource.goToFileUri) : undefined,
|
||||
)),
|
||||
false
|
||||
);
|
||||
|
@ -112,8 +114,9 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
|||
label: this.label,
|
||||
multiDiffSourceUri: this.multiDiffSource.toString(),
|
||||
resources: this.initialResources?.map(resource => ({
|
||||
originalUri: resource.original?.toString(),
|
||||
modifiedUri: resource.modified?.toString(),
|
||||
originalUri: resource.originalUri?.toString(),
|
||||
modifiedUri: resource.modifiedUri?.toString(),
|
||||
goToFileUri: resource.goToFileUri?.toString(),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
@ -159,8 +162,8 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
|||
|
||||
try {
|
||||
[original, modified] = await Promise.all([
|
||||
r.original ? this._textModelService.createModelReference(r.original) : undefined,
|
||||
r.modified ? this._textModelService.createModelReference(r.modified) : undefined,
|
||||
r.originalUri ? this._textModelService.createModelReference(r.originalUri) : undefined,
|
||||
r.modifiedUri ? this._textModelService.createModelReference(r.modifiedUri) : undefined,
|
||||
]);
|
||||
if (original) { store2.add(original); }
|
||||
if (modified) { store2.add(modified); }
|
||||
|
@ -171,8 +174,9 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const uri = (r.modified ?? r.original)!;
|
||||
return new ConstLazyPromise<IDocumentDiffItem>({
|
||||
const uri = (r.modifiedUri ?? r.originalUri)!;
|
||||
return new ConstLazyPromise<IDocumentDiffItemWithMultiDiffEditorItem>({
|
||||
multiDiffEditorItem: r,
|
||||
original: original?.object.textEditorModel,
|
||||
modified: modified?.object.textEditorModel,
|
||||
get options() {
|
||||
|
@ -187,7 +191,7 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
|||
}
|
||||
}),
|
||||
});
|
||||
}, i => JSON.stringify([i.modified?.toString(), i.original?.toString()]));
|
||||
}, i => JSON.stringify([i.modifiedUri?.toString(), i.originalUri?.toString()]));
|
||||
|
||||
const documents = observableValue<readonly LazyPromise<IDocumentDiffItem>[]>('documents', []);
|
||||
|
||||
|
@ -239,8 +243,8 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
|||
|
||||
public readonly resources = derived(this, reader => this._resolvedSource.cachedPromiseResult.read(reader)?.data?.resources.read(reader));
|
||||
private readonly _isDirtyObservables = mapObservableArrayCached(this, this.resources.map(r => r ?? []), res => {
|
||||
const isModifiedDirty = res.modified ? isUriDirty(this._textFileService, res.modified) : constObservable(false);
|
||||
const isOriginalDirty = res.original ? isUriDirty(this._textFileService, res.original) : constObservable(false);
|
||||
const isModifiedDirty = res.modifiedUri ? isUriDirty(this._textFileService, res.modifiedUri) : constObservable(false);
|
||||
const isOriginalDirty = res.originalUri ? isUriDirty(this._textFileService, res.originalUri) : constObservable(false);
|
||||
return derived(reader => /** @description modifiedDirty||originalDirty */ isModifiedDirty.read(reader) || isOriginalDirty.read(reader));
|
||||
}, i => i.getKey());
|
||||
private readonly _isDirtyObservable = derived(this, reader => this._isDirtyObservables.read(reader).some(isDirty => isDirty.read(reader)))
|
||||
|
@ -291,6 +295,10 @@ export class MultiDiffEditorInput extends EditorInput implements ILanguageSuppor
|
|||
};
|
||||
}
|
||||
|
||||
export interface IDocumentDiffItemWithMultiDiffEditorItem extends IDocumentDiffItem {
|
||||
multiDiffEditorItem: MultiDiffEditorItem;
|
||||
}
|
||||
|
||||
function isUriDirty(textFileService: ITextFileService, uri: URI) {
|
||||
return observableFromEvent(
|
||||
Event.filter(textFileService.files.onDidChangeDirty, e => e.resource.toString() === uri.toString()),
|
||||
|
@ -361,6 +369,7 @@ interface ISerializedMultiDiffEditorInput {
|
|||
resources: {
|
||||
originalUri: string | undefined;
|
||||
modifiedUri: string | undefined;
|
||||
goToFileUri: string | undefined;
|
||||
}[] | undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,16 +33,17 @@ export interface IResolvedMultiDiffSource {
|
|||
|
||||
export class MultiDiffEditorItem {
|
||||
constructor(
|
||||
readonly original: URI | undefined,
|
||||
readonly modified: URI | undefined,
|
||||
readonly originalUri: URI | undefined,
|
||||
readonly modifiedUri: URI | undefined,
|
||||
readonly goToFileUri: URI | undefined,
|
||||
) {
|
||||
if (!original && !modified) {
|
||||
if (!originalUri && !modifiedUri) {
|
||||
throw new BugIndicatingError('Invalid arguments');
|
||||
}
|
||||
}
|
||||
|
||||
getKey(): string {
|
||||
return JSON.stringify([this.modified?.toString(), this.original?.toString()]);
|
||||
return JSON.stringify([this.modifiedUri?.toString(), this.originalUri?.toString()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ export class ScmMultiDiffSourceResolver implements IMultiDiffSourceResolver {
|
|||
class ScmResolvedMultiDiffSource implements IResolvedMultiDiffSource {
|
||||
private readonly _resources = observableFromEvent<MultiDiffEditorItem[]>(
|
||||
this._group.onDidChangeResources,
|
||||
() => /** @description resources */ this._group.resources.map(e => new MultiDiffEditorItem(e.multiDiffEditorOriginalUri, e.multiDiffEditorModifiedUri))
|
||||
() => /** @description resources */ this._group.resources.map(e => new MultiDiffEditorItem(e.multiDiffEditorOriginalUri, e.multiDiffEditorModifiedUri, e.sourceUri))
|
||||
);
|
||||
readonly resources = new ValueWithChangeEventFromObservable(this._resources);
|
||||
|
||||
|
|
Loading…
Reference in a new issue