From 77a8508e6d8011a8d9f058f0e7ea2fdff7a56fe3 Mon Sep 17 00:00:00 2001 From: Max <135263966+verifizieren@users.noreply.github.com> Date: Sat, 16 May 2026 02:40:43 +0200 Subject: [PATCH] Trim surrounding whitespace from line comment token A line comment token configured with leading or trailing whitespace (e.g. " #") broke Toggle Line Comment: the inserted comment could never be detected again, so each toggle stacked another comment instead of removing it. Whitespace around the marker is not semantically meaningful - spacing on insertion is controlled by `editor.comments.insertSpace` - so the token is now trimmed when the comment configuration is resolved. This also keeps the `${LINE_COMMENT}` snippet variable and notebook inline variable detection consistent. No built-in language is affected. Fixes #249958 --- .../languageConfigurationRegistry.ts | 7 +- .../test/browser/lineCommentCommand.test.ts | 66 +++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/common/languages/languageConfigurationRegistry.ts b/src/vs/editor/common/languages/languageConfigurationRegistry.ts index 0dffed073d4c2..09397ccdd98d4 100644 --- a/src/vs/editor/common/languages/languageConfigurationRegistry.ts +++ b/src/vs/editor/common/languages/languageConfigurationRegistry.ts @@ -457,10 +457,13 @@ export class ResolvedLanguageConfiguration { const comments: ICommentsConfiguration = {}; if (commentRule.lineComment) { + // Surrounding whitespace is not part of the comment marker; spacing on + // insertion is controlled by the `editor.comments.insertSpace` setting. + // Keeping it would break comment toggling, see #249958. if (typeof commentRule.lineComment === 'string') { - comments.lineCommentToken = commentRule.lineComment; + comments.lineCommentToken = commentRule.lineComment.trim(); } else { - comments.lineCommentToken = commentRule.lineComment.comment; + comments.lineCommentToken = commentRule.lineComment.comment.trim(); comments.lineCommentNoIndent = commentRule.lineComment.noIndent; } } diff --git a/src/vs/editor/contrib/comment/test/browser/lineCommentCommand.test.ts b/src/vs/editor/contrib/comment/test/browser/lineCommentCommand.test.ts index 8c4e0b6dce244..e733835de19da 100644 --- a/src/vs/editor/contrib/comment/test/browser/lineCommentCommand.test.ts +++ b/src/vs/editor/contrib/comment/test/browser/lineCommentCommand.test.ts @@ -101,6 +101,72 @@ suite('Editor Contrib - Line Comment Command', () => { ); }); + test('toggle line comment when the comment token has surrounding whitespace (#249958)', function () { + const testLineCommentCommand = createTestCommandHelper( + { lineComment: ' !@# ' }, + (accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true) + ); + + // Adds the trimmed comment token + testLineCommentCommand( + [ + 'some text' + ], + new Selection(1, 1, 1, 1), + [ + '!@# some text' + ], + new Selection(1, 5, 1, 5) + ); + + // Toggling again removes it instead of stacking another comment + testLineCommentCommand( + [ + '!@# some text' + ], + new Selection(1, 1, 1, 1), + [ + 'some text' + ], + new Selection(1, 1, 1, 1) + ); + }); + + test('toggle line comment when the object-form comment token has surrounding whitespace (#249958)', function () { + const testLineCommentCommand = createTestCommandHelper( + { lineComment: { comment: ' !@# ', noIndent: true } }, + (accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true) + ); + + // Adds the trimmed comment token at the first column (noIndent) + testLineCommentCommand( + [ + 'some text', + '\tsome more text' + ], + new Selection(2, 1, 2, 1), + [ + 'some text', + '!@# \tsome more text' + ], + new Selection(2, 5, 2, 5) + ); + + // Toggling again removes it instead of stacking another comment + testLineCommentCommand( + [ + 'some text', + '!@# \tsome more text' + ], + new Selection(2, 1, 2, 1), + [ + 'some text', + '\tsome more text' + ], + new Selection(2, 1, 2, 1) + ); + }); + function createSimpleModel(lines: string[]): ISimpleModel { return { getLineContent: (lineNumber: number) => {