Skip to content

Commit 7190530

Browse files
authored
readonly - adopt readOnlyMessage for readonly mode (microsoft#185756)
1 parent f596237 commit 7190530

File tree

28 files changed

+134
-58
lines changed

28 files changed

+134
-58
lines changed

build/lib/i18n.resources.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,10 @@
382382
"name": "vs/workbench/services/files",
383383
"project": "vscode-workbench"
384384
},
385+
{
386+
"name": "vs/workbench/services/filesConfiguration",
387+
"project": "vscode-workbench"
388+
},
385389
{
386390
"name": "vs/workbench/services/history",
387391
"project": "vscode-workbench"

src/vs/platform/files/common/files.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,6 @@ export const enum FileSystemProviderCapabilities {
584584
export interface IFileSystemProvider {
585585

586586
readonly capabilities: FileSystemProviderCapabilities;
587-
readonly readOnlyMessage?: IMarkdownString;
588587
readonly onDidChangeCapabilities: Event<void>;
589588

590589
readonly onDidChangeFile: Event<readonly IFileChange[]>;
@@ -688,6 +687,20 @@ export function hasFileAtomicDeleteCapability(provider: IFileSystemProvider): pr
688687
return !!(provider.capabilities & FileSystemProviderCapabilities.FileAtomicDelete);
689688
}
690689

690+
export interface IFileSystemProviderWithReadonlyCapability extends IFileSystemProvider {
691+
692+
readonly capabilities: FileSystemProviderCapabilities.Readonly & FileSystemProviderCapabilities;
693+
694+
/**
695+
* An optional message to show in the UI to explain why the file system is readonly.
696+
*/
697+
readonly readOnlyMessage?: IMarkdownString;
698+
}
699+
700+
export function hasReadonlyCapability(provider: IFileSystemProvider): provider is IFileSystemProviderWithReadonlyCapability {
701+
return !!(provider.capabilities & FileSystemProviderCapabilities.Readonly);
702+
}
703+
691704
export enum FileSystemProviderErrorCode {
692705
FileExists = 'EntryExists',
693706
FileNotFound = 'EntryNotFound',

src/vs/workbench/browser/contextkeys.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ export class WorkbenchContextKeysHandler extends Disposable {
307307
this.activeEditorAvailableEditorIds.set(editors.join(','));
308308
}
309309

310-
this.activeEditorIsReadonly.set(activeEditorPane.input.hasCapability(EditorInputCapabilities.Readonly));
310+
this.activeEditorIsReadonly.set(!!activeEditorPane.input.isReadonly());
311311
const primaryEditorResource = EditorResourceAccessor.getOriginalUri(activeEditorPane.input, { supportSideBySide: SideBySideEditor.PRIMARY });
312312
this.activeEditorCanToggleReadonly.set(!!primaryEditorResource && this.fileService.hasProvider(primaryEditorResource) && !this.fileService.hasCapability(primaryEditorResource, FileSystemProviderCapabilities.Readonly));
313313
} else {

src/vs/workbench/browser/parts/editor/editorAutoSave.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export class EditorAutoSave extends Disposable implements IWorkbenchContribution
9191
}
9292

9393
private maybeTriggerAutoSave(reason: SaveReason, editorIdentifier?: IEditorIdentifier): void {
94-
if (editorIdentifier?.editor.hasCapability(EditorInputCapabilities.Readonly) || editorIdentifier?.editor.hasCapability(EditorInputCapabilities.Untitled)) {
94+
if (editorIdentifier?.editor.isReadonly() || editorIdentifier?.editor.hasCapability(EditorInputCapabilities.Untitled)) {
9595
return; // no auto save for readonly or untitled editors
9696
}
9797

src/vs/workbench/browser/parts/editor/editorStatus.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri';
1313
import { Action } from 'vs/base/common/actions';
1414
import { Language } from 'vs/base/common/platform';
1515
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
16-
import { IFileEditorInput, EditorResourceAccessor, IEditorPane, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor';
16+
import { IFileEditorInput, EditorResourceAccessor, IEditorPane, SideBySideEditor } from 'vs/workbench/common/editor';
1717
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
1818
import { Disposable, MutableDisposable, DisposableStore } from 'vs/base/common/lifecycle';
1919
import { IEditorAction } from 'vs/editor/common/editorCommon';
@@ -340,7 +340,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution {
340340
return this.quickInputService.pick([{ label: localize('noEditor', "No text editor active at this time") }]);
341341
}
342342

343-
if (this.editorService.activeEditor?.hasCapability(EditorInputCapabilities.Readonly)) {
343+
if (this.editorService.activeEditor?.isReadonly()) {
344344
return this.quickInputService.pick([{ label: localize('noWritableCodeEditor', "The active code editor is read-only.") }]);
345345
}
346346

@@ -1271,7 +1271,7 @@ export class ChangeEOLAction extends Action2 {
12711271
return;
12721272
}
12731273

1274-
if (editorService.activeEditor?.hasCapability(EditorInputCapabilities.Readonly)) {
1274+
if (editorService.activeEditor?.isReadonly()) {
12751275
await quickInputService.pick([{ label: localize('noWritableCodeEditor', "The active code editor is read-only.") }]);
12761276
return;
12771277
}
@@ -1288,7 +1288,7 @@ export class ChangeEOLAction extends Action2 {
12881288
const eol = await quickInputService.pick(EOLOptions, { placeHolder: localize('pickEndOfLine', "Select End of Line Sequence"), activeItem: EOLOptions[selectedIndex] });
12891289
if (eol) {
12901290
const activeCodeEditor = getCodeEditor(editorService.activeTextEditorControl);
1291-
if (activeCodeEditor?.hasModel() && !editorService.activeEditor?.hasCapability(EditorInputCapabilities.Readonly)) {
1291+
if (activeCodeEditor?.hasModel() && !editorService.activeEditor?.isReadonly()) {
12921292
textModel = activeCodeEditor.getModel();
12931293
textModel.pushStackElement();
12941294
textModel.pushEOL(eol.eol);
@@ -1353,7 +1353,7 @@ export class ChangeEncodingAction extends Action2 {
13531353
let action: IQuickPickItem | undefined;
13541354
if (encodingSupport instanceof UntitledTextEditorInput) {
13551355
action = saveWithEncodingPick;
1356-
} else if (activeEditorPane.input.hasCapability(EditorInputCapabilities.Readonly)) {
1356+
} else if (activeEditorPane.input.isReadonly()) {
13571357
action = reopenWithEncodingPick;
13581358
} else {
13591359
action = await quickInputService.pick([reopenWithEncodingPick, saveWithEncodingPick], { placeHolder: localize('pickAction', "Select Action"), matchOnDetail: true });

src/vs/workbench/browser/parts/editor/editorWithViewState.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
1717
import { IExtUri } from 'vs/base/common/resources';
1818
import { IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
1919
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
20-
import { IMarkdownString } from 'vs/base/common/htmlContent';
2120

2221
/**
2322
* Base class of editors that want to store and restore view state.
@@ -54,12 +53,6 @@ export abstract class AbstractEditorWithViewState<T extends object> extends Edit
5453
super.setEditorVisible(visible, group);
5554
}
5655

57-
protected readonlyValues(isReadonly: boolean | IMarkdownString | undefined): { readOnly: boolean; readOnlyMessage: IMarkdownString | undefined } {
58-
const readOnly = !!isReadonly;
59-
const readOnlyMessage = typeof isReadonly !== 'boolean' ? isReadonly : undefined;
60-
return { readOnly, readOnlyMessage };
61-
}
62-
6356
private onWillCloseEditor(e: IEditorCloseEvent): void {
6457
const editor = e.editor;
6558
if (editor === this.input) {

src/vs/workbench/browser/parts/editor/textDiffEditor.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { isObject, assertIsDefined, withNullAsUndefined } from 'vs/base/common/t
99
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
1010
import { IDiffEditorOptions, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions';
1111
import { AbstractTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor';
12-
import { TEXT_DIFF_EDITOR_ID, IEditorFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorOpenContext, EditorInputCapabilities, isEditorInput, isTextEditorViewState, createTooLargeFileError } from 'vs/workbench/common/editor';
12+
import { TEXT_DIFF_EDITOR_ID, IEditorFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorOpenContext, isEditorInput, isTextEditorViewState, createTooLargeFileError } from 'vs/workbench/common/editor';
1313
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
1414
import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions';
1515
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
@@ -160,7 +160,7 @@ export class TextDiffEditor extends AbstractTextEditor<IDiffEditorViewState> imp
160160
// a resolved model might have more specific information about being
161161
// readonly or not that the input did not have.
162162
control.updateOptions({
163-
...this.readonlyValues(resolvedDiffEditorModel.modifiedModel?.isReadonly()),
163+
...this.getReadonlyConfiguration(resolvedDiffEditorModel.modifiedModel?.isReadonly()),
164164
originalEditable: !resolvedDiffEditorModel.originalModel?.isReadonly()
165165
});
166166

@@ -280,21 +280,19 @@ export class TextDiffEditor extends AbstractTextEditor<IDiffEditorViewState> imp
280280
}
281281

282282
protected override getConfigurationOverrides(): IDiffEditorOptions {
283-
const readOnly = this.input instanceof DiffEditorInput && this.input.modified.hasCapability(EditorInputCapabilities.Readonly);
284-
285283
return {
286284
...super.getConfigurationOverrides(),
287-
readOnly,
288-
originalEditable: this.input instanceof DiffEditorInput && !this.input.original.hasCapability(EditorInputCapabilities.Readonly),
285+
...this.getReadonlyConfiguration(this.input?.isReadonly()),
286+
originalEditable: this.input instanceof DiffEditorInput && !this.input.original.isReadonly(),
289287
lineDecorationsWidth: '2ch'
290288
};
291289
}
292290

293291
protected override updateReadonly(input: EditorInput): void {
294292
if (input instanceof DiffEditorInput) {
295293
this.diffEditorControl?.updateOptions({
296-
readOnly: input.hasCapability(EditorInputCapabilities.Readonly),
297-
originalEditable: !input.original.hasCapability(EditorInputCapabilities.Readonly),
294+
...this.getReadonlyConfiguration(input.isReadonly()),
295+
originalEditable: !input.original.isReadonly(),
298296
});
299297
} else {
300298
super.updateReadonly(input);

src/vs/workbench/browser/parts/editor/textEditor.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Emitter, Event } from 'vs/base/common/event';
1010
import { isObject, assertIsDefined } from 'vs/base/common/types';
1111
import { MutableDisposable } from 'vs/base/common/lifecycle';
1212
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
13-
import { IEditorOpenContext, EditorInputCapabilities, IEditorPaneSelection, EditorPaneSelectionCompareResult, EditorPaneSelectionChangeReason, IEditorPaneWithSelection, IEditorPaneSelectionChangeEvent } from 'vs/workbench/common/editor';
13+
import { IEditorOpenContext, IEditorPaneSelection, EditorPaneSelectionCompareResult, EditorPaneSelectionChangeReason, IEditorPaneWithSelection, IEditorPaneSelectionChangeEvent } from 'vs/workbench/common/editor';
1414
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
1515
import { computeEditorAriaLabel } from 'vs/workbench/browser/editor';
1616
import { AbstractEditorWithViewState } from 'vs/workbench/browser/parts/editor/editorWithViewState';
@@ -28,6 +28,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
2828
import { IEditorOptions, ITextEditorOptions, TextEditorSelectionRevealType, TextEditorSelectionSource } from 'vs/platform/editor/common/editor';
2929
import { ICursorPositionChangedEvent } from 'vs/editor/common/cursorEvents';
3030
import { IFileService } from 'vs/platform/files/common/files';
31+
import { IMarkdownString } from 'vs/base/common/htmlContent';
3132

3233
export interface IEditorConfiguration {
3334
editor: object;
@@ -139,16 +140,22 @@ export abstract class AbstractTextEditor<T extends IEditorViewState> extends Abs
139140
}
140141

141142
protected updateReadonly(input: EditorInput): void {
142-
const readOnly = input.hasCapability(EditorInputCapabilities.Readonly);
143-
this.updateEditorControlOptions({ readOnly });
143+
this.updateEditorControlOptions({ ...this.getReadonlyConfiguration(input.isReadonly()) });
144+
}
145+
146+
protected getReadonlyConfiguration(isReadonly: boolean | IMarkdownString | undefined): { readOnly: boolean; readOnlyMessage: IMarkdownString | undefined } {
147+
return {
148+
readOnly: !!isReadonly,
149+
readOnlyMessage: typeof isReadonly !== 'boolean' ? isReadonly : undefined
150+
};
144151
}
145152

146153
protected getConfigurationOverrides(): ICodeEditorOptions {
147154
return {
148155
overviewRulerLanes: 3,
149156
lineNumbersMinChars: 3,
150157
fixedOverflowWidgets: true,
151-
...this.readonlyValues(this.input?.isReadonly()),
158+
...this.getReadonlyConfiguration(this.input?.isReadonly()),
152159
renderValidationDecorations: 'on' // render problems even in readonly editors (https://github.com/microsoft/vscode/issues/89057)
153160
};
154161
}

src/vs/workbench/browser/parts/editor/textResourceEditor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export abstract class AbstractTextResourceEditor extends AbstractTextCodeEditor<
9292
// was already asked for being readonly or not. The rationale is that
9393
// a resolved model might have more specific information about being
9494
// readonly or not that the input did not have.
95-
control.updateOptions(this.readonlyValues(resolvedModel.isReadonly()));
95+
control.updateOptions(this.getReadonlyConfiguration(resolvedModel.isReadonly()));
9696
}
9797

9898
/**

src/vs/workbench/common/editor/editorInput.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export abstract class EditorInput extends AbstractEditorInput {
125125
return (this.capabilities & capability) !== 0;
126126
}
127127

128-
isReadonly(): boolean | IMarkdownString | undefined {
128+
isReadonly(): boolean | IMarkdownString {
129129
return this.hasCapability(EditorInputCapabilities.Readonly);
130130
}
131131

0 commit comments

Comments
 (0)