Skip to content

Commit f52d436

Browse files
authored
Fix auto-insert ignoring language-specific editor.tabSize (#8768)
2 parents 5cfcbd7 + b057a1d commit f52d436

File tree

2 files changed

+84
-9
lines changed

2 files changed

+84
-9
lines changed

src/lsptoolshost/autoInsert/onAutoInsert.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as vscode from 'vscode';
7-
87
import {
98
FormattingOptions,
109
InsertTextFormat,
@@ -82,10 +81,20 @@ export function registerOnAutoInsert(languageServer: RoslynLanguageServer, langu
8281
// We need to calculate what that position would be after the change is applied and send that to the server.
8382
const position = vscodeRange.start.translate(0, change.text.length - rangeLength);
8483

84+
const formattingOptions = getFormattingOptions(document);
85+
8586
source.cancel();
8687
source = new vscode.CancellationTokenSource();
8788
try {
88-
await applyAutoInsertEdit(position, changeTrimmed, e.textDocument, uri, languageServer, source.token);
89+
await applyAutoInsertEdit(
90+
position,
91+
changeTrimmed,
92+
e.textDocument,
93+
uri,
94+
formattingOptions,
95+
languageServer,
96+
source.token
97+
);
8998
} catch (e) {
9099
if (e instanceof vscode.CancellationError) {
91100
return;
@@ -101,10 +110,10 @@ async function applyAutoInsertEdit(
101110
changeTextTrimmed: string,
102111
textDocumentIdentifier: TextDocumentIdentifier,
103112
uri: vscode.Uri,
113+
formattingOptions: FormattingOptions,
104114
languageServer: RoslynLanguageServer,
105115
token: vscode.CancellationToken
106116
) {
107-
const formattingOptions = getFormattingOptions();
108117
const request: RoslynProtocol.OnAutoInsertParams = {
109118
_vs_textDocument: textDocumentIdentifier,
110119
_vs_position: position,
@@ -142,9 +151,18 @@ async function applyAutoInsertEdit(
142151
}
143152
}
144153

145-
function getFormattingOptions(): FormattingOptions {
146-
const editorConfig = vscode.workspace.getConfiguration('editor');
147-
const tabSize = editorConfig.get<number>('tabSize') ?? 4;
148-
const insertSpaces = editorConfig.get<boolean>('insertSpaces') ?? true;
154+
function getFormattingOptions(document: vscode.TextDocument): FormattingOptions {
155+
const editorSettings = vscode.workspace.getConfiguration('editor', document);
156+
const detectIndentation = editorSettings.get<boolean>('detectIndentation');
157+
158+
const editor = detectIndentation
159+
? vscode.window.visibleTextEditors.find((e) => e.document === document)
160+
: undefined;
161+
162+
// VSCode guarantees that retrieving the editor.options.tabSize will return a number
163+
const tabSize = (editor?.options.tabSize as number | undefined) ?? editorSettings.get<number>('tabSize') ?? 4;
164+
// VSCode guarantees that retrieving the editor.options.insertSpaces will return a boolean
165+
const insertSpaces =
166+
(editor?.options.insertSpaces as boolean | undefined) ?? editorSettings.get<boolean>('insertSpaces') ?? true;
149167
return FormattingOptions.create(tabSize, insertSpaces);
150168
}

test/lsptoolshost/integrationTests/onAutoInsert.integration.test.ts

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
closeAllEditorsAsync,
1212
openFileInWorkspaceAsync,
1313
revertActiveFile,
14-
sleep,
1514
waitForExpectedResult,
1615
} from './integrationHelpers';
1716
import { describe, beforeAll, beforeEach, afterAll, test, expect, afterEach } from '@jest/globals';
@@ -36,7 +35,6 @@ describe(`OnAutoInsert Tests`, () => {
3635
});
3736

3837
test('Triple slash inserts doc comment snippet', async () => {
39-
await sleep(1);
4038
await vscode.window.activeTextEditor!.edit((editBuilder) => {
4139
editBuilder.insert(new vscode.Position(2, 6), '/');
4240
});
@@ -110,6 +108,65 @@ describe(`OnAutoInsert Tests`, () => {
110108
}
111109
);
112110
});
111+
112+
test('Enter inside braces respects language-specific tabSize', async () => {
113+
// Set global tabSize to 2 and C# tabSize to 4
114+
const globalConfig = vscode.workspace.getConfiguration('editor');
115+
const csharpConfig = vscode.workspace.getConfiguration('editor', {
116+
languageId: 'csharp',
117+
uri: vscode.window.activeTextEditor!.document.uri,
118+
});
119+
120+
const originalGlobalTabSize = globalConfig.get('tabSize');
121+
const originalCsharpTabSize = csharpConfig.get('tabSize');
122+
123+
try {
124+
// Turn off detect indentation to ensure it consistently uses the settings.
125+
await globalConfig.update('detectIndentation', false, vscode.ConfigurationTarget.Global);
126+
127+
// Customize tab sizes
128+
await globalConfig.update('tabSize', 4, vscode.ConfigurationTarget.Global);
129+
await csharpConfig.update('tabSize', 2, vscode.ConfigurationTarget.Global);
130+
131+
await vscode.window.activeTextEditor!.edit((editBuilder) => {
132+
editBuilder.insert(new vscode.Position(11, 15), '\n');
133+
});
134+
135+
const expectedLines = [
136+
'class DocComments',
137+
'{',
138+
' //',
139+
' string M(int param1, string param2)',
140+
' {',
141+
' return null;',
142+
' }',
143+
'',
144+
' /// <summary>',
145+
'',
146+
' /// </summary>',
147+
' void M2()',
148+
' {',
149+
' ', // Should be 2 spaces (C# setting), not 4 (global setting)
150+
' }',
151+
'}',
152+
'',
153+
];
154+
155+
await waitForExpectedResult<string | undefined>(
156+
async () => vscode.window.activeTextEditor?.document.getText(),
157+
10000,
158+
100,
159+
(input) => {
160+
expect(input).toBe(expectedLines.join(EOL));
161+
}
162+
);
163+
} finally {
164+
// Restore original settings
165+
await globalConfig.update('detectIndentation', true, vscode.ConfigurationTarget.Global);
166+
await globalConfig.update('tabSize', originalGlobalTabSize, vscode.ConfigurationTarget.Global);
167+
await csharpConfig.update('tabSize', originalCsharpTabSize, vscode.ConfigurationTarget.Global);
168+
}
169+
});
113170
});
114171

115172
function normalizeNewlines(text: string | undefined): string | undefined {

0 commit comments

Comments
 (0)