Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
c3e4504
Initial plan
Copilot Feb 25, 2026
b857fb3
Update renameTool and usagesTool: skip registration when no providers…
Copilot Feb 25, 2026
1026d57
Simplify empty-set check: size === 0 is sufficient
Copilot Feb 25, 2026
5d91224
fixes vscode-internalbacklog#6911
isidorn Feb 27, 2026
9eb854b
Merge branch 'main' into copilot/update-tool-descriptions-languages
jrieken Mar 4, 2026
35f486e
Fix compile errors in renameTool.test.ts and usagesTool.test.ts
Copilot Mar 4, 2026
94b3617
Use markdownDescription for theme properties
mjbvz Mar 13, 2026
1de403d
Remove sign in dialog experiment
cwebster-99 Mar 20, 2026
00fdd06
Initial plan
Copilot Mar 20, 2026
c49415c
Add history navigation (arrow up/down) to inline chat v3 input widget
Copilot Mar 20, 2026
c39fcb0
marker hover: add MenuId for status bar actions and register Fix action
jrieken Mar 20, 2026
4c9386b
Merge pull request #303427 from microsoft/copilot/fix-inline-chat-his…
jrieken Mar 20, 2026
3f90040
Support for nested subagents (#302944)
aeschli Mar 20, 2026
deca020
Fix CI status widget header label vertical alignment (#303455)
benibenj Mar 20, 2026
bf939ee
Initial plan
Copilot Mar 20, 2026
54cd946
Merge branch 'main' into joh/marker-hover-menu-actions
jrieken Mar 20, 2026
b4317ec
Sessions - add commit skill and adopt it in the pull requestion creat…
lszomoru Mar 20, 2026
b5b6be6
Avoid getting redacted due to keyword matches (#287739)
chrmarti Mar 20, 2026
8e050e3
feat: add chat.editing.autoNavigation setting to control auto-jump af…
Copilot Mar 20, 2026
f134790
inlineChat: use stepped resize for input widget width
jrieken Mar 20, 2026
f0524cc
Merge pull request #303454 from microsoft/joh/marker-hover-menu-actions
jrieken Mar 20, 2026
7846f89
rename setting to chat.editing.revealNextChangeOnResolve
Copilot Mar 20, 2026
17f2de9
Sessions - fix code review toolbar contribution (#303464)
lszomoru Mar 20, 2026
e084e07
Fix SCM count badge to use visible repositories (#300796)
kno Mar 20, 2026
b63b483
Merge branch 'main' into isidorn/final-parrotfish
isidorn Mar 20, 2026
8a041c1
Merge pull request #298304 from microsoft/isidorn/final-parrotfish
isidorn Mar 20, 2026
490922d
multi select adoption for compressed tree
benibenj Mar 20, 2026
d3669e4
Merge branch 'main' into copilot/update-tool-descriptions-languages
jrieken Mar 20, 2026
0be9de2
Merge branch 'main' into joh/inline-chat-stepped-resize
jrieken Mar 20, 2026
8550c40
Merge branch 'main' into meerkat
cwebster-99 Mar 20, 2026
4d4d448
Merge pull request #303511 from microsoft/benibenj/presidential-ox
benibenj Mar 20, 2026
dd7c043
Merge pull request #303473 from microsoft/copilot/add-option-to-disab…
jrieken Mar 20, 2026
f0a991b
Merge pull request #303476 from microsoft/joh/inline-chat-stepped-resize
jrieken Mar 20, 2026
d05f2f2
inlineChat: shared history service with persistence (#303471)
jrieken Mar 20, 2026
702949b
Bump fast-xml-parser from 5.5.6 to 5.5.7 in /build (#303324)
dependabot[bot] Mar 20, 2026
a2fa4ea
Merge pull request #297684 from microsoft/copilot/update-tool-descrip…
jrieken Mar 20, 2026
d5a7770
Sessions: Enhance auxiliary bar widget functionality and styling (#30…
mrleemurray Mar 20, 2026
c8fda5b
Sessions: Add session count display to agent session sections (#303514)
mrleemurray Mar 20, 2026
3a3a936
Sessions - add new context keys for ahead/behind (#303520)
lszomoru Mar 20, 2026
4743b94
fix(git): correctly pluralise `line_length` input validation (#301071)
BerkeBat Mar 20, 2026
b6e7b33
Merge branch 'main' into dev/mjbvz/near-octopus
mjbvz Mar 20, 2026
2d90926
Merge pull request #301419 from mjbvz/dev/mjbvz/near-octopus
mjbvz Mar 20, 2026
5fc1ff4
Merge pull request #303365 from microsoft/meerkat
cwebster-99 Mar 20, 2026
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
14 changes: 7 additions & 7 deletions build/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion extensions/git/src/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ export class GitCommitInputBoxDiagnosticsManager {
const threshold = index === 0 ? inputValidationSubjectLength ?? inputValidationLength : inputValidationLength;

if (line.text.length > threshold) {
const diagnostic = new Diagnostic(line.range, l10n.t('{0} characters over {1} in current line', line.text.length - threshold, threshold), this.severity);
const charactersOver = line.text.length - threshold;
const lineLengthMessage = charactersOver === 1
? l10n.t('{0} character over {1} in current line', charactersOver, threshold)
: l10n.t('{0} characters over {1} in current line', charactersOver, threshold);
const diagnostic = new Diagnostic(line.range, lineLengthMessage, this.severity);
diagnostic.code = DiagnosticCodes.line_length;

diagnostics.push(diagnostic);
Expand Down
1 change: 1 addition & 0 deletions src/vs/base/browser/ui/hover/hoverWidget.css
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
.monaco-hover .hover-row.status-bar .actions .action-container .action .icon {
padding-right: 4px;
vertical-align: middle;
font-size: inherit;
}

.monaco-hover .hover-row.status-bar .actions .action-container a {
Expand Down
7 changes: 5 additions & 2 deletions src/vs/base/browser/ui/tree/asyncDataTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { IDragAndDropData } from '../../dnd.js';
import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, IListMouseEvent, IListTouchEvent, IListVirtualDelegate } from '../list/list.js';
import { IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, IListMouseEvent, IListTouchEvent, IListVirtualDelegate, NotSelectableGroupIdType } from '../list/list.js';
import { ElementsDragAndDropData, ListViewTargetSector } from '../list/listView.js';
import { IListStyles } from '../list/listWidget.js';
import { ComposedTreeDelegate, TreeFindMode, IAbstractTreeOptions, IAbstractTreeOptionsUpdate, TreeFindMatchType, AbstractTreePart, LabelFuzzyScore, FindFilter, FindController, ITreeFindToggleChangeEvent, IFindControllerOptions, IStickyScrollDelegate, AbstractTree } from './abstractTree.js';
Expand Down Expand Up @@ -1309,7 +1309,10 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
diffIdentityProvider: options.diffIdentityProvider && {
getId(node: IAsyncDataTreeNode<TInput, T>): { toString(): string } {
return options.diffIdentityProvider!.getId(node.element as T);
}
},
getGroupId: options.diffIdentityProvider!.getGroupId ? (node: IAsyncDataTreeNode<TInput, T>): number | NotSelectableGroupIdType => {
return options.diffIdentityProvider!.getGroupId!(node.element as T);
} : undefined
}
};

Expand Down
12 changes: 9 additions & 3 deletions src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { IIdentityProvider } from '../list/list.js';
import { IIdentityProvider, NotSelectableGroupIdType } from '../list/list.js';
import { getVisibleState, IIndexTreeModelSpliceOptions, isFilterResult } from './indexTreeModel.js';
import { IObjectTreeModel, IObjectTreeModelOptions, IObjectTreeModelSetChildrenOptions, ObjectTreeModel } from './objectTreeModel.js';
import { ICollapseStateChangeEvent, IObjectTreeElement, ITreeListSpliceData, ITreeModel, ITreeModelSpliceEvent, ITreeNode, TreeError, TreeFilterResult, TreeVisibility, WeakMapper } from './tree.js';
Expand Down Expand Up @@ -113,7 +113,10 @@ interface ICompressedObjectTreeModelOptions<T, TFilterData> extends IObjectTreeM
const wrapIdentityProvider = <T>(base: IIdentityProvider<T>): IIdentityProvider<ICompressedTreeNode<T>> => ({
getId(node) {
return node.elements.map(e => base.getId(e).toString()).join('\0');
}
},
getGroupId: base.getGroupId ? (node: ICompressedTreeNode<T>): number | NotSelectableGroupIdType => {
return base.getGroupId!(node.elements[node.elements.length - 1]);
} : undefined
});

// Exported only for test reasons, do not use directly
Expand Down Expand Up @@ -380,7 +383,10 @@ function mapOptions<T, TFilterData>(compressedNodeUnwrapper: CompressedNodeUnwra
identityProvider: options.identityProvider && {
getId(node: ICompressedTreeNode<T>): { toString(): string } {
return options.identityProvider!.getId(compressedNodeUnwrapper(node));
}
},
getGroupId: options.identityProvider!.getGroupId ? (node: ICompressedTreeNode<T>): number | NotSelectableGroupIdType => {
return options.identityProvider!.getGroupId!(compressedNodeUnwrapper(node));
} : undefined
},
sorter: options.sorter && {
compare(node: ICompressedTreeNode<T>, otherNode: ICompressedTreeNode<T>): number {
Expand Down
90 changes: 90 additions & 0 deletions src/vs/base/test/browser/ui/tree/objectTree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { IIdentityProvider, IListVirtualDelegate } from '../../../../browser/ui/
import { ICompressedTreeNode } from '../../../../browser/ui/tree/compressedObjectTreeModel.js';
import { CompressibleObjectTree, ICompressibleTreeRenderer, ObjectTree } from '../../../../browser/ui/tree/objectTree.js';
import { ITreeNode, ITreeRenderer } from '../../../../browser/ui/tree/tree.js';
import { runWithFakedTimers } from '../../../common/timeTravelScheduler.js';
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../common/utils.js';

function getRowsTextContent(container: HTMLElement): string[] {
Expand All @@ -16,6 +17,17 @@ function getRowsTextContent(container: HTMLElement): string[] {
return rows.map(row => row.querySelector('.monaco-tl-contents')!.textContent!);
}

function clickElement(element: HTMLElement, ctrlKey = false): void {
element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, ctrlKey, button: 0 }));
element.dispatchEvent(new MouseEvent('click', { bubbles: true, ctrlKey, button: 0 }));
}

function dispatchKeydown(element: HTMLElement, key: string, code: string, keyCode: number): void {
const keyboardEvent = new KeyboardEvent('keydown', { bubbles: true, key, code });
Object.defineProperty(keyboardEvent, 'keyCode', { get: () => keyCode });
element.dispatchEvent(keyboardEvent);
}

suite('ObjectTree', function () {

suite('TreeNavigator', function () {
Expand Down Expand Up @@ -231,6 +243,84 @@ suite('ObjectTree', function () {
tree.setChildren(null, [{ element: 100 }, { element: 101 }, { element: 102 }, { element: 103 }]);
assert.deepStrictEqual(tree.getFocus(), [101]);
});

test('updateOptions preserves wrapped identity provider in view options', function () {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';

const delegate = new Delegate();
const renderer = new Renderer();
const identityProvider = {
getId(element: number): { toString(): string } {
return `${element}`;
},
getGroupId(element: number): number {
return element % 2;
}
};

const tree = new ObjectTree<number>('test', container, delegate, [renderer], { identityProvider });

try {
tree.layout(200);
tree.setChildren(null, [{ element: 0 }, { element: 1 }, { element: 2 }, { element: 3 }]);

const firstRow = container.querySelector('.monaco-list-row[data-index="0"]') as HTMLElement;
const secondRow = container.querySelector('.monaco-list-row[data-index="1"]') as HTMLElement;
clickElement(firstRow);
assert.deepStrictEqual(tree.getSelection(), [0]);

tree.updateOptions({ indent: 12 });

clickElement(secondRow, true);

assert.deepStrictEqual(tree.getSelection(), [1]);
} finally {
tree.dispose();
}
});

test('updateOptions preserves wrapped accessibility provider for type navigation re-announce', async function () {
const container = document.createElement('div');
container.style.width = '200px';
container.style.height = '200px';

const delegate = new Delegate();
const renderer = new Renderer();
const accessibilityProvider = {
getAriaLabel(element: number): string {
assert.strictEqual(typeof element, 'number');
return `aria ${element}`;
},
getWidgetAriaLabel(): string {
return 'tree';
}
};

const tree = new ObjectTree<number>('test', container, delegate, [renderer], {
accessibilityProvider,
keyboardNavigationLabelProvider: {
getKeyboardNavigationLabel: () => 'a'
}
});

try {
await runWithFakedTimers({ useFakeTimers: true }, async () => {
tree.layout(200);
tree.setChildren(null, [{ element: 0 }]);
tree.setFocus([0]);
tree.domFocus();

tree.updateOptions({ indent: 12 });

dispatchKeydown(tree.getHTMLElement(), 'a', 'KeyA', 65);
await Promise.resolve();
});
} finally {
tree.dispose();
}
});
});

suite('CompressibleObjectTree', function () {
Expand Down
44 changes: 42 additions & 2 deletions src/vs/editor/contrib/hover/browser/markerHoverParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { CodeActionKind, CodeActionSet, CodeActionTrigger, CodeActionTriggerSour
import { MarkerController, NextMarkerAction } from '../../gotoError/browser/gotoError.js';
import { HoverAnchor, HoverAnchorType, IEditorHoverParticipant, IEditorHoverRenderContext, IHoverPart, IRenderedHoverPart, IRenderedHoverParts, RenderedHoverParts } from './hoverTypes.js';
import * as nls from '../../../../nls.js';
import { IMenuService, MenuId, MenuItemAction } from '../../../../platform/actions/common/actions.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
import { ITextEditorOptions } from '../../../../platform/editor/common/editor.js';
import { IMarker, IMarkerData, MarkerSeverity } from '../../../../platform/markers/common/markers.js';
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
Expand Down Expand Up @@ -65,6 +67,8 @@ export class MarkerHoverParticipant implements IEditorHoverParticipant<MarkerHov
@IMarkerDecorationsService private readonly _markerDecorationsService: IMarkerDecorationsService,
@IOpenerService private readonly _openerService: IOpenerService,
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
@IMenuService private readonly _menuService: IMenuService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
) { }

public computeSync(anchor: HoverAnchor, lineDecorations: IModelDecoration[]): MarkerHover[] {
Expand Down Expand Up @@ -206,12 +210,38 @@ export class MarkerHoverParticipant implements IEditorHoverParticipant<MarkerHov
}
}

// Menu-contributed actions (e.g. fix with inline chat)
const menuActions: MenuItemAction[] = [];
for (const [, actions] of this._menuService.getMenuActions(MenuId.MarkerHoverStatusBar, this._contextKeyService)) {
for (const action of actions) {
if (action instanceof MenuItemAction && action.enabled) {
menuActions.push(action);
}
}
}
const renderMenuActions = () => {
for (const action of menuActions) {
context.statusBar.addAction({
label: action.label,
commandId: action.id,
iconClass: action.class,
run: () => {
context.hide();
this._editor.setSelection(Range.lift(markerHover.range));
action.run();
}
});
}
};

if (!this._editor.getOption(EditorOption.readOnly)) {
const quickfixPlaceholderElement = context.statusBar.append($('div'));
if (this.recentMarkerCodeActionsInfo) {
if (IMarkerData.makeKey(this.recentMarkerCodeActionsInfo.marker) === IMarkerData.makeKey(markerHover.marker)) {
if (!this.recentMarkerCodeActionsInfo.hasCodeActions) {
quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available");
if (menuActions.length === 0) {
quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available");
}
}
} else {
this.recentMarkerCodeActionsInfo = undefined;
Expand All @@ -230,7 +260,12 @@ export class MarkerHoverParticipant implements IEditorHoverParticipant<MarkerHov

if (!this.recentMarkerCodeActionsInfo.hasCodeActions) {
actions.dispose();
quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available");
if (menuActions.length === 0) {
quickfixPlaceholderElement.textContent = nls.localize('noQuickFixes', "No quick fixes available");
} else {
quickfixPlaceholderElement.style.display = 'none';
}
renderMenuActions();
return;
}
quickfixPlaceholderElement.style.display = 'none';
Expand Down Expand Up @@ -274,13 +309,18 @@ export class MarkerHoverParticipant implements IEditorHoverParticipant<MarkerHov
});
}

renderMenuActions();

// Notify that the contents have changed given we added
// actions to the hover
// https://github.com/microsoft/vscode/issues/250424
context.onContentsChanged();

}, onUnexpectedError);
} else {
renderMenuActions();
}

return disposables;
}

Expand Down
1 change: 1 addition & 0 deletions src/vs/platform/actions/common/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ export class MenuId {
static readonly ChatViewSessionTitleNavigationToolbar = new MenuId('ChatViewSessionTitleNavigationToolbar');
static readonly ChatViewSessionTitleToolbar = new MenuId('ChatViewSessionTitleToolbar');
static readonly ChatContextUsageActions = new MenuId('ChatContextUsageActions');
static readonly MarkerHoverStatusBar = new MenuId('MarkerHoverParticipant.StatusBar');

/**
* Create or reuse a `MenuId` with the given identifier
Expand Down
Loading
Loading