Skip to content
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
32 changes: 25 additions & 7 deletions src/lsptoolshost/autoInsert/onAutoInsert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';

import {
FormattingOptions,
InsertTextFormat,
Expand Down Expand Up @@ -82,10 +81,20 @@ export function registerOnAutoInsert(languageServer: RoslynLanguageServer, langu
// We need to calculate what that position would be after the change is applied and send that to the server.
const position = vscodeRange.start.translate(0, change.text.length - rangeLength);

const formattingOptions = getFormattingOptions(document);

source.cancel();
source = new vscode.CancellationTokenSource();
try {
await applyAutoInsertEdit(position, changeTrimmed, e.textDocument, uri, languageServer, source.token);
await applyAutoInsertEdit(
position,
changeTrimmed,
e.textDocument,
uri,
formattingOptions,
languageServer,
source.token
);
} catch (e) {
if (e instanceof vscode.CancellationError) {
return;
Expand All @@ -101,10 +110,10 @@ async function applyAutoInsertEdit(
changeTextTrimmed: string,
textDocumentIdentifier: TextDocumentIdentifier,
uri: vscode.Uri,
formattingOptions: FormattingOptions,
languageServer: RoslynLanguageServer,
token: vscode.CancellationToken
) {
const formattingOptions = getFormattingOptions();
const request: RoslynProtocol.OnAutoInsertParams = {
_vs_textDocument: textDocumentIdentifier,
_vs_position: position,
Expand Down Expand Up @@ -142,9 +151,18 @@ async function applyAutoInsertEdit(
}
}

function getFormattingOptions(): FormattingOptions {
const editorConfig = vscode.workspace.getConfiguration('editor');
const tabSize = editorConfig.get<number>('tabSize') ?? 4;
const insertSpaces = editorConfig.get<boolean>('insertSpaces') ?? true;
function getFormattingOptions(document: vscode.TextDocument): FormattingOptions {
const editorSettings = vscode.workspace.getConfiguration('editor', document);
const detectIndentation = editorSettings.get<boolean>('detectIndentation');

const editor = detectIndentation
? vscode.window.visibleTextEditors.find((e) => e.document === document)
: undefined;

// VSCode guarantees that retrieving the editor.options.tabSize will return a number
const tabSize = (editor?.options.tabSize as number | undefined) ?? editorSettings.get<number>('tabSize') ?? 4;
// VSCode guarantees that retrieving the editor.options.insertSpaces will return a boolean
const insertSpaces =
(editor?.options.insertSpaces as boolean | undefined) ?? editorSettings.get<boolean>('insertSpaces') ?? true;
return FormattingOptions.create(tabSize, insertSpaces);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
closeAllEditorsAsync,
openFileInWorkspaceAsync,
revertActiveFile,
sleep,
waitForExpectedResult,
} from './integrationHelpers';
import { describe, beforeAll, beforeEach, afterAll, test, expect, afterEach } from '@jest/globals';
Expand All @@ -36,7 +35,6 @@ describe(`OnAutoInsert Tests`, () => {
});

test('Triple slash inserts doc comment snippet', async () => {
await sleep(1);
await vscode.window.activeTextEditor!.edit((editBuilder) => {
editBuilder.insert(new vscode.Position(2, 6), '/');
});
Expand Down Expand Up @@ -110,6 +108,65 @@ describe(`OnAutoInsert Tests`, () => {
}
);
});

test('Enter inside braces respects language-specific tabSize', async () => {
// Set global tabSize to 2 and C# tabSize to 4
const globalConfig = vscode.workspace.getConfiguration('editor');
const csharpConfig = vscode.workspace.getConfiguration('editor', {
languageId: 'csharp',
uri: vscode.window.activeTextEditor!.document.uri,
});

const originalGlobalTabSize = globalConfig.get('tabSize');
const originalCsharpTabSize = csharpConfig.get('tabSize');

try {
// Turn off detect indentation to ensure it consistently uses the settings.
await globalConfig.update('detectIndentation', false, vscode.ConfigurationTarget.Global);

// Customize tab sizes
await globalConfig.update('tabSize', 4, vscode.ConfigurationTarget.Global);
await csharpConfig.update('tabSize', 2, vscode.ConfigurationTarget.Global);

await vscode.window.activeTextEditor!.edit((editBuilder) => {
editBuilder.insert(new vscode.Position(11, 15), '\n');
});

const expectedLines = [
'class DocComments',
'{',
' //',
' string M(int param1, string param2)',
' {',
' return null;',
' }',
'',
' /// <summary>',
'',
' /// </summary>',
' void M2()',
' {',
' ', // Should be 2 spaces (C# setting), not 4 (global setting)
' }',
'}',
'',
];

await waitForExpectedResult<string | undefined>(
async () => vscode.window.activeTextEditor?.document.getText(),
10000,
100,
(input) => {
expect(input).toBe(expectedLines.join(EOL));
}
);
} finally {
// Restore original settings
await globalConfig.update('detectIndentation', true, vscode.ConfigurationTarget.Global);
await globalConfig.update('tabSize', originalGlobalTabSize, vscode.ConfigurationTarget.Global);
await csharpConfig.update('tabSize', originalCsharpTabSize, vscode.ConfigurationTarget.Global);
}
});
});

function normalizeNewlines(text: string | undefined): string | undefined {
Expand Down