mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-24 12:19:20 +00:00
Make type signature of groupBy more accurate (#272395)
See #272263, it currently assumes that all keys of K will be defined. This still isn't perfect, because it says that the returned object might contain a key with value `undefined`, but in reality, if a key is defined, it will have a value. So now usages of this with Object.entries and so on are slighly wrong, but that's preferable IMO.
This commit is contained in:
@@ -19,8 +19,8 @@ export type INumberDictionary<V> = Record<number, V>;
|
|||||||
* Groups the collection into a dictionary based on the provided
|
* Groups the collection into a dictionary based on the provided
|
||||||
* group function.
|
* group function.
|
||||||
*/
|
*/
|
||||||
export function groupBy<K extends string | number | symbol, V>(data: readonly V[], groupFn: (element: V) => K): Record<K, V[]> {
|
export function groupBy<K extends string | number | symbol, V>(data: readonly V[], groupFn: (element: V) => K): Partial<Record<K, V[]>> {
|
||||||
const result: Record<K, V[]> = Object.create(null);
|
const result: Partial<Record<K, V[]>> = Object.create(null);
|
||||||
for (const element of data) {
|
for (const element of data) {
|
||||||
const key = groupFn(element);
|
const key = groupFn(element);
|
||||||
let target = result[key];
|
let target = result[key];
|
||||||
|
|||||||
@@ -206,7 +206,9 @@ export class DisposableTracker implements IDisposableTracker {
|
|||||||
const continuations = groupBy([...prevStarts].map(d => getStackTracePath(d)[i]), v => v);
|
const continuations = groupBy([...prevStarts].map(d => getStackTracePath(d)[i]), v => v);
|
||||||
delete continuations[stackTracePath[i]];
|
delete continuations[stackTracePath[i]];
|
||||||
for (const [cont, set] of Object.entries(continuations)) {
|
for (const [cont, set] of Object.entries(continuations)) {
|
||||||
stackTraceFormattedLines.unshift(` - stacktraces of ${set.length} other leaks continue with ${cont}`);
|
if (set) {
|
||||||
|
stackTraceFormattedLines.unshift(` - stacktraces of ${set.length} other leaks continue with ${cont}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stackTraceFormattedLines.unshift(line);
|
stackTraceFormattedLines.unshift(line);
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ suite('Collections', () => {
|
|||||||
const grouped = collections.groupBy(source, x => x.key);
|
const grouped = collections.groupBy(source, x => x.key);
|
||||||
|
|
||||||
// Group 1
|
// Group 1
|
||||||
assert.strictEqual(grouped[group1].length, 2);
|
assert.strictEqual(grouped[group1]?.length, 2);
|
||||||
assert.strictEqual(grouped[group1][0].value, value1);
|
assert.strictEqual(grouped[group1][0].value, value1);
|
||||||
assert.strictEqual(grouped[group1][1].value, value2);
|
assert.strictEqual(grouped[group1][1].value, value2);
|
||||||
|
|
||||||
// Group 2
|
// Group 2
|
||||||
assert.strictEqual(grouped[group2].length, 1);
|
assert.strictEqual(grouped[group2]?.length, 1);
|
||||||
assert.strictEqual(grouped[group2][0].value, value3);
|
assert.strictEqual(grouped[group2][0].value, value3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -79,11 +79,11 @@ export class ModePickerActionItem extends ActionWidgetDropdownActionViewItem {
|
|||||||
mode => mode.source?.storage === PromptsStorage.extension && mode.source.extensionId.value === productService.defaultChatAgent?.chatExtensionId ?
|
mode => mode.source?.storage === PromptsStorage.extension && mode.source.extensionId.value === productService.defaultChatAgent?.chatExtensionId ?
|
||||||
'builtin' : 'custom');
|
'builtin' : 'custom');
|
||||||
|
|
||||||
const customBuiltinModeActions = customModes.builtin.map(mode => {
|
const customBuiltinModeActions = customModes.builtin?.map(mode => {
|
||||||
const action = makeActionFromCustomMode(mode, currentMode);
|
const action = makeActionFromCustomMode(mode, currentMode);
|
||||||
action.category = builtInCategory;
|
action.category = builtInCategory;
|
||||||
return action;
|
return action;
|
||||||
});
|
}) ?? [];
|
||||||
|
|
||||||
const orderedModes = coalesce([
|
const orderedModes = coalesce([
|
||||||
agentMode && makeAction(agentMode, currentMode),
|
agentMode && makeAction(agentMode, currentMode),
|
||||||
|
|||||||
@@ -410,9 +410,9 @@ export class BaseIssueReporterService extends Disposable {
|
|||||||
return ext.isTheme ? 'themes' : 'nonThemes';
|
return ext.isTheme ? 'themes' : 'nonThemes';
|
||||||
});
|
});
|
||||||
|
|
||||||
const numberOfThemeExtesions = themes && themes.length;
|
const numberOfThemeExtesions = (themes && themes.length) ?? 0;
|
||||||
this.issueReporterModel.update({ numberOfThemeExtesions, enabledNonThemeExtesions: nonThemes, allExtensions: installedExtensions });
|
this.issueReporterModel.update({ numberOfThemeExtesions, enabledNonThemeExtesions: nonThemes, allExtensions: installedExtensions });
|
||||||
this.updateExtensionTable(nonThemes, numberOfThemeExtesions);
|
this.updateExtensionTable(nonThemes ?? [], numberOfThemeExtesions);
|
||||||
if (this.disableExtensions || installedExtensions.length === 0) {
|
if (this.disableExtensions || installedExtensions.length === 0) {
|
||||||
(<HTMLButtonElement>this.getElementById('disableExtensions')).disabled = true;
|
(<HTMLButtonElement>this.getElementById('disableExtensions')).disabled = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ class TestMarkersModel extends MarkersModel {
|
|||||||
|
|
||||||
Object.keys(byResource).forEach(key => {
|
Object.keys(byResource).forEach(key => {
|
||||||
const markers = byResource[key];
|
const markers = byResource[key];
|
||||||
const resource = markers[0].resource;
|
if (markers) {
|
||||||
|
const resource = markers[0].resource;
|
||||||
|
|
||||||
this.setResourceMarkers([[resource, markers]]);
|
this.setResourceMarkers([[resource, markers]]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,9 +117,9 @@ export class ListMcpServerCommand extends Action2 {
|
|||||||
const firstRun = pick.items.length === 0;
|
const firstRun = pick.items.length === 0;
|
||||||
pick.items = [
|
pick.items = [
|
||||||
{ id: '$add', label: localize('mcp.addServer', 'Add Server'), description: localize('mcp.addServer.description', 'Add a new server configuration'), alwaysShow: true, iconClass: ThemeIcon.asClassName(Codicon.add) },
|
{ id: '$add', label: localize('mcp.addServer', 'Add Server'), description: localize('mcp.addServer.description', 'Add a new server configuration'), alwaysShow: true, iconClass: ThemeIcon.asClassName(Codicon.add) },
|
||||||
...Object.values(servers).filter(s => s.length).flatMap((servers): (ItemType | IQuickPickSeparator)[] => [
|
...Object.values(servers).filter(s => s!.length).flatMap((servers): (ItemType | IQuickPickSeparator)[] => [
|
||||||
{ type: 'separator', label: servers[0].collection.label, id: servers[0].collection.id },
|
{ type: 'separator', label: servers![0].collection.label, id: servers![0].collection.id },
|
||||||
...servers.map(server => ({
|
...servers!.map(server => ({
|
||||||
id: server.definition.id,
|
id: server.definition.id,
|
||||||
label: server.definition.label,
|
label: server.definition.label,
|
||||||
description: McpConnectionState.toString(server.connectionState.read(reader)),
|
description: McpConnectionState.toString(server.connectionState.read(reader)),
|
||||||
|
|||||||
@@ -778,7 +778,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
|
|||||||
|
|
||||||
for (const _handle in deletesByHandle) {
|
for (const _handle in deletesByHandle) {
|
||||||
const handle = parseInt(_handle);
|
const handle = parseInt(_handle);
|
||||||
const ids = deletesByHandle[handle];
|
const ids = deletesByHandle[handle]!;
|
||||||
const cell = this.getCellByHandle(handle);
|
const cell = this.getCellByHandle(handle);
|
||||||
cell?.deltaCellStatusBarItems(ids, []);
|
cell?.deltaCellStatusBarItems(ids, []);
|
||||||
ids.forEach(id => this._statusBarItemIdToCellMap.delete(id));
|
ids.forEach(id => this._statusBarItemIdToCellMap.delete(id));
|
||||||
|
|||||||
@@ -504,11 +504,15 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer<SCMHistoryItemVie
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!historyItemRefs) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Group history item references by icon
|
// Group history item references by icon
|
||||||
const historyItemRefByIconId = groupBy2(historyItemRefs, ref => ThemeIcon.isThemeIcon(ref.icon) ? ref.icon.id : '');
|
const historyItemRefByIconId = groupBy2(historyItemRefs, ref => ThemeIcon.isThemeIcon(ref.icon) ? ref.icon.id : '');
|
||||||
for (const [key, historyItemRefs] of Object.entries(historyItemRefByIconId)) {
|
for (const [key, historyItemRefs] of Object.entries(historyItemRefByIconId)) {
|
||||||
// Skip badges without an icon
|
// Skip badges without an icon
|
||||||
if (key === '') {
|
if (key === '' || !historyItemRefs) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user