From b094e2f7dd0f12247df4a33b94d7930640d9f2bc Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sat, 28 Feb 2026 15:04:28 -0800 Subject: [PATCH] Fix inline reference at block start rendering on its own line (#298497) Copilot-authored message: Fix inline reference at block start rendering on its own line When an inlineReference is the first item in a chat response (no preceding markdown), it creates a standalone markdownContent with default MarkdownString properties. The subsequent markdown from the model has different properties (e.g. isTrusted: true), causing canMergeMarkdownStrings to return false. This leaves them as separate content parts, rendering the inline reference link on its own line. Fix by detecting when the previous item consists solely of synthesized content-ref links (via isContentRefOnly check) and merging them by prepending the reference text while adopting the incoming markdown's properties. Fixes #278191 --- .../contrib/chat/common/widget/annotations.ts | 34 +++++++++++++++++-- .../test/common/widget/annotations.test.ts | 34 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/chat/common/widget/annotations.ts b/src/vs/workbench/contrib/chat/common/widget/annotations.ts index b43079b5add..e1b417e5f9b 100644 --- a/src/vs/workbench/contrib/chat/common/widget/annotations.ts +++ b/src/vs/workbench/contrib/chat/common/widget/annotations.ts @@ -57,9 +57,25 @@ export function annotateSpecialMarkdownContent(response: Iterable${item.content.value}`; @@ -88,6 +104,18 @@ export function annotateSpecialMarkdownContent(response: Iterable { + const result = annotateSpecialMarkdownContent([ + { kind: 'inlineReference', inlineReference: URI.parse('file:///index.ts'), name: 'index.ts' }, + { kind: 'markdownContent', content: new MarkdownString(' is the entry point', { isTrusted: true, supportThemeIcons: true }) }, + ]); + + assert.strictEqual(result.length, 1); + const md = result[0] as IChatMarkdownContent; + assert.ok(md.content.value.includes('[index.ts]')); + assert.ok(md.content.value.includes('_vscodecontentref_')); + assert.ok(md.content.value.endsWith(' is the entry point')); + assert.ok(md.inlineReferences); + assert.strictEqual(md.content.isTrusted, true); + assert.strictEqual(md.content.supportThemeIcons, true); + }); + + test('inline reference after regular text does not force-merge incompatible markdown', () => { + const result = annotateSpecialMarkdownContent([ + content('See '), + { kind: 'inlineReference', inlineReference: URI.parse('file:///index.ts'), name: 'index.ts' }, + { kind: 'markdownContent', content: new MarkdownString(' more info', { isTrusted: true, supportThemeIcons: true }) }, + ]); + + // The first item has "See [index.ts](...)" with default markdown properties, + // the second item has different properties - they must stay separate. + assert.strictEqual(result.length, 2); + const first = result[0] as IChatMarkdownContent; + assert.ok(first.content.value.startsWith('See ')); + assert.ok(first.inlineReferences); + const second = result[1] as IChatMarkdownContent; + assert.strictEqual(second.content.value, ' more info'); + assert.strictEqual(second.content.isTrusted, true); + }); }); });