Skip to content

Commit 0fd2883

Browse files
author
Benjamin Pasero
committed
Allow to configure "files.defaultLanguage" to use current language (fix microsoft#78903)
1 parent 0bce136 commit 0fd2883

10 files changed

Lines changed: 81 additions & 19 deletions

File tree

extensions/configuration-editing/src/settingsDocumentHelper.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ export class SettingsDocument {
3434

3535
// files.defaultLanguage
3636
if (location.path[0] === 'files.defaultLanguage') {
37-
return this.provideLanguageCompletionItems(location, range);
37+
return this.provideLanguageCompletionItems(location, range).then(items => {
38+
39+
// Add special item 'active-editor'
40+
return [this.newSimpleCompletionItem(JSON.stringify('active-editor'), range, localize('activeEditor', "Use the language mode of the currently active text editor if any")), ...items];
41+
});
3842
}
3943

4044
return this.provideLanguageOverridesCompletionItems(location, position);
@@ -153,7 +157,7 @@ export class SettingsDocument {
153157
return Promise.resolve(completions);
154158
}
155159

156-
private provideLanguageCompletionItems(_location: Location, range: vscode.Range, formatFunc: (string: string) => string = (l) => JSON.stringify(l)): vscode.ProviderResult<vscode.CompletionItem[]> {
160+
private provideLanguageCompletionItems(_location: Location, range: vscode.Range, formatFunc: (string: string) => string = (l) => JSON.stringify(l)): Thenable<vscode.CompletionItem[]> {
157161
return vscode.languages.getLanguages().then(languages => {
158162
const completionItems = [];
159163
const configuration = vscode.workspace.getConfiguration();

src/vs/editor/contrib/rename/rename.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class RenameController implements IEditorContribution {
115115
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
116116
@IThemeService private readonly _themeService: IThemeService,
117117
) {
118-
this._renameInputField = new IdleValue(() => this._dispoableStore.add(new RenameInputField(this.editor, this._themeService, this._contextKeyService)));
118+
this._renameInputField = this._dispoableStore.add(new IdleValue(() => this._dispoableStore.add(new RenameInputField(this.editor, this._themeService, this._contextKeyService))));
119119
}
120120

121121
dispose(): void {

src/vs/editor/contrib/suggest/suggestController.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export class SuggestController implements IEditorContribution {
121121
this.editor = editor;
122122
this.model = new SuggestModel(this.editor, editorWorker);
123123

124-
this.widget = new IdleValue(() => {
124+
this.widget = this._toDispose.add(new IdleValue(() => {
125125

126126
const widget = this._instantiationService.createInstance(SuggestWidget, this.editor);
127127

@@ -168,11 +168,11 @@ export class SuggestController implements IEditorContribution {
168168

169169

170170
return widget;
171-
});
171+
}));
172172

173-
this._alternatives = new IdleValue(() => {
173+
this._alternatives = this._toDispose.add(new IdleValue(() => {
174174
return this._toDispose.add(new SuggestAlternatives(this.editor, this._contextKeyService));
175-
});
175+
}));
176176

177177
this._toDispose.add(_instantiationService.createInstance(WordContextKey, editor));
178178

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

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,21 @@ export class UntitledTextEditorInput extends TextEditorInput implements IEncodin
2828

2929
private static readonly MEMOIZER = createMemoizer();
3030

31-
private cachedModel: UntitledTextEditorModel | null = null;
32-
private modelResolve: Promise<UntitledTextEditorModel & IResolvedTextEditorModel> | null = null;
33-
3431
private readonly _onDidModelChangeContent = this._register(new Emitter<void>());
3532
readonly onDidModelChangeContent = this._onDidModelChangeContent.event;
3633

3734
private readonly _onDidModelChangeEncoding = this._register(new Emitter<void>());
3835
readonly onDidModelChangeEncoding = this._onDidModelChangeEncoding.event;
3936

37+
private cachedModel: UntitledTextEditorModel | null = null;
38+
private modelResolve: Promise<UntitledTextEditorModel & IResolvedTextEditorModel> | null = null;
39+
40+
private preferredMode: string | undefined;
41+
4042
constructor(
4143
resource: URI,
4244
private readonly _hasAssociatedFilePath: boolean,
43-
private preferredMode: string | undefined,
45+
preferredMode: string | undefined,
4446
private readonly initialValue: string | undefined,
4547
private preferredEncoding: string | undefined,
4648
@IInstantiationService private readonly instantiationService: IInstantiationService,
@@ -52,6 +54,10 @@ export class UntitledTextEditorInput extends TextEditorInput implements IEncodin
5254
) {
5355
super(resource, editorService, editorGroupService, textFileService);
5456

57+
if (preferredMode) {
58+
this.setMode(preferredMode);
59+
}
60+
5561
this.registerListeners();
5662
}
5763

@@ -225,10 +231,20 @@ export class UntitledTextEditorInput extends TextEditorInput implements IEncodin
225231
}
226232

227233
setMode(mode: string): void {
228-
this.preferredMode = mode;
234+
let actualMode: string | undefined = undefined;
235+
if (mode === 'active-editor') {
236+
// support the special 'active-editor' mode by
237+
// looking up the language mode from the currently
238+
// active text editor if any
239+
actualMode = this.editorService.activeTextEditorMode;
240+
} else {
241+
actualMode = mode;
242+
}
229243

230-
if (this.cachedModel) {
231-
this.cachedModel.setMode(mode);
244+
this.preferredMode = actualMode;
245+
246+
if (this.preferredMode && this.cachedModel) {
247+
this.cachedModel.setMode(this.preferredMode);
232248
}
233249
}
234250

src/vs/workbench/contrib/files/browser/files.contribution.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ configurationRegistry.registerConfiguration({
314314
'files.hotExit': hotExitConfiguration,
315315
'files.defaultLanguage': {
316316
'type': 'string',
317-
'description': nls.localize('defaultLanguage', "The default language mode that is assigned to new files.")
317+
'description': nls.localize('defaultLanguage', "The default language mode that is assigned to new files. If configured to `active-editor`, will use the language mode of the currently active text editor if any.")
318318
},
319319
'files.maxMemoryForLargeFilesMB': {
320320
'type': 'number',

src/vs/workbench/services/editor/browser/editorService.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,19 @@ export class EditorService extends Disposable implements EditorServiceImpl {
186186
return undefined;
187187
}
188188

189+
get activeTextEditorMode(): string | undefined {
190+
let activeCodeEditor: ICodeEditor | undefined = undefined;
191+
192+
const activeTextEditorWidget = this.activeTextEditorWidget;
193+
if (isDiffEditor(activeTextEditorWidget)) {
194+
activeCodeEditor = activeTextEditorWidget.getModifiedEditor();
195+
} else {
196+
activeCodeEditor = activeTextEditorWidget;
197+
}
198+
199+
return activeCodeEditor?.getModel()?.getLanguageIdentifier().language;
200+
}
201+
189202
get count(): number {
190203
return this.editorsObserver.count;
191204
}
@@ -839,6 +852,7 @@ export class DelegatingEditorService implements IEditorService {
839852
get activeEditor(): IEditorInput | undefined { return this.editorService.activeEditor; }
840853
get activeControl(): IVisibleEditor | undefined { return this.editorService.activeControl; }
841854
get activeTextEditorWidget(): ICodeEditor | IDiffEditor | undefined { return this.editorService.activeTextEditorWidget; }
855+
get activeTextEditorMode(): string | undefined { return this.editorService.activeTextEditorMode; }
842856
get visibleEditors(): ReadonlyArray<IEditorInput> { return this.editorService.visibleEditors; }
843857
get visibleControls(): ReadonlyArray<IVisibleEditor> { return this.editorService.visibleControls; }
844858
get visibleTextEditorWidgets(): ReadonlyArray<ICodeEditor | IDiffEditor> { return this.editorService.visibleTextEditorWidgets; }

src/vs/workbench/services/editor/common/editorService.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ export interface IEditorService {
105105
*/
106106
readonly activeTextEditorWidget: ICodeEditor | IDiffEditor | undefined;
107107

108+
/**
109+
* The currently active text editor mode or `undefined` if there is currently no active
110+
* editor or the active editor widget is neither a text nor a diff editor. If the active
111+
* editor is a diff editor, the modified side's mode will be taken.
112+
*/
113+
readonly activeTextEditorMode: string | undefined;
114+
108115
/**
109116
* All editors that are currently visible. An editor is visible when it is opened in an
110117
* editor group and active in that group. Multiple editor groups can be opened at the same time.

src/vs/workbench/services/editor/test/browser/editorService.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { UntitledTextEditorModel } from 'vs/workbench/common/editor/untitledText
3131
import { NullFileSystemProvider } from 'vs/platform/files/test/common/nullFileSystemProvider';
3232
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
3333
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
34-
import { CancellationToken } from 'vscode';
34+
import { CancellationToken } from 'vs/base/common/cancellation';
3535

3636
const TEST_EDITOR_ID = 'MyTestEditorForEditorService';
3737
const TEST_EDITOR_INPUT_ID = 'testEditorInputForEditorService';
@@ -163,6 +163,7 @@ suite('EditorService', () => {
163163
assert.equal(service.visibleControls.length, 1);
164164
assert.equal(service.visibleControls[0], editor);
165165
assert.ok(!service.activeTextEditorWidget);
166+
assert.ok(!service.activeTextEditorMode);
166167
assert.equal(service.visibleTextEditorWidgets.length, 0);
167168
assert.equal(service.isOpen(input), true);
168169
assert.equal(service.getOpened({ resource: input.getResource() }), input);

src/vs/workbench/test/common/editor/untitledTextEditor.test.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
99
import { IUntitledTextEditorService, UntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
1010
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1111
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
12-
import { workbenchInstantiationService } from 'vs/workbench/test/workbenchTestServices';
12+
import { workbenchInstantiationService, TestEditorService } from 'vs/workbench/test/workbenchTestServices';
1313
import { UntitledTextEditorModel } from 'vs/workbench/common/editor/untitledTextEditorModel';
1414
import { IModeService } from 'vs/editor/common/services/modeService';
1515
import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
@@ -18,6 +18,7 @@ import { timeout } from 'vs/base/common/async';
1818
import { snapshotToString } from 'vs/workbench/services/textfile/common/textfiles';
1919
import { ModesRegistry, PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
2020
import { IWorkingCopyService, IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService';
21+
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
2122

2223
export class TestUntitledTextEditorService extends UntitledTextEditorService {
2324
get(resource: URI) { return super.get(resource); }
@@ -27,10 +28,11 @@ export class TestUntitledTextEditorService extends UntitledTextEditorService {
2728
class ServiceAccessor {
2829
constructor(
2930
@IUntitledTextEditorService public readonly untitledTextEditorService: TestUntitledTextEditorService,
31+
@IEditorService public readonly editorService: TestEditorService,
3032
@IWorkingCopyService public readonly workingCopyService: IWorkingCopyService,
3133
@IModeService public readonly modeService: ModeServiceImpl,
32-
@IConfigurationService public readonly testConfigurationService: TestConfigurationService) {
33-
}
34+
@IConfigurationService public readonly testConfigurationService: TestConfigurationService
35+
) { }
3436
}
3537

3638
suite('Workbench untitled text editors', () => {
@@ -234,6 +236,23 @@ suite('Workbench untitled text editors', () => {
234236
input.dispose();
235237
});
236238

239+
test('Untitled created with files.defaultLanguage setting (active-editor)', () => {
240+
const config = accessor.testConfigurationService;
241+
config.setUserConfiguration('files', { 'defaultLanguage': 'active-editor' });
242+
243+
accessor.editorService.activeTextEditorMode = 'typescript';
244+
245+
const service = accessor.untitledTextEditorService;
246+
const input = service.createOrGet();
247+
248+
assert.equal(input.getMode(), 'typescript');
249+
250+
config.setUserConfiguration('files', { 'defaultLanguage': undefined });
251+
accessor.editorService.activeTextEditorMode = undefined;
252+
253+
input.dispose();
254+
});
255+
237256
test('Untitled created with mode overrides files.defaultLanguage setting', () => {
238257
const mode = 'typescript';
239258
const defaultLanguage = 'javascript';

src/vs/workbench/test/workbenchTestServices.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,7 @@ export class TestEditorService implements EditorServiceImpl {
905905

906906
activeControl!: IVisibleEditor;
907907
activeTextEditorWidget: any;
908+
activeTextEditorMode: any;
908909
activeEditor!: IEditorInput;
909910
editors: ReadonlyArray<IEditorInput> = [];
910911
mostRecentlyActiveEditors: ReadonlyArray<IEditorIdentifier> = [];

0 commit comments

Comments
 (0)