Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't listen on menu changed, method 2 #219964

Merged
merged 3 commits into from
Jul 8, 2024
Merged

Don't listen on menu changed, method 2 #219964

merged 3 commits into from
Jul 8, 2024

Conversation

alexr00
Copy link
Member

@alexr00 alexr00 commented Jul 4, 2024

This time, instead of only updating the tree elements who's actions are visible (selected, focused, focusing), update all tree items that the context change applies to, as before. However, the context key change event is now per tree renderer, not per menu.
Fixes #213145

This time, instead of only updating the tree elements who's actions are visible (selected, focused, focusing), update all tree items that the context change applies to, as before. However, the context key change event is now per tree renderer, not per menu.
Fixes #213145
@alexr00 alexr00 self-assigned this Jul 4, 2024
@alexr00 alexr00 enabled auto-merge (squash) July 4, 2024 13:24
@alexr00 alexr00 disabled auto-merge July 4, 2024 13:24
@alexr00 alexr00 requested a review from bpasero July 4, 2024 13:24
Copy link
Member Author

@alexr00 alexr00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bpasero, are you the right person to review menuService changes?

@bpasero
Copy link
Member

bpasero commented Jul 4, 2024

Yielding for Jo.

Copy link
Member

@jrieken jrieken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nerd snipped

@@ -272,6 +272,7 @@ export interface IMenuChangeEvent {
export interface IMenu extends IDisposable {
readonly onDidChange: Event<IMenuChangeEvent>;
getActions(options?: IMenuActionOptions): [string, Array<MenuItemAction | SubmenuItemAction>][];
contexts(): ReadonlySet<string>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this but I would suggest to move it out of IMenu and into IMenuService, like the following

export interface IMenuService {
    // ... existing stuff

  getMenuContexts(id: MenuId): ReadonlySet<string>;
}

The implementation would be like yours: create, read and dispose the actual menu. We could then complement this with IMenuService#getMenuActions(id: MenudId, options?: IMenuActionOptions): [string, Array<MenuItemAction | SubmenuItemAction>][];) which would be the equivalent of: create menu, get actions, dispose menu.

Those two methods would be the "dead" counter-part of IMenu (which is listening and emitting). We could also add IMenuService#getMenuData which would encapsulate those two concepts: context and action groups but no eventing. So, maybe alltogether

interface IMenuData {
  contexts(): ReadonlySet<string>;
  actions: [string, Array<MenuItemAction | SubmenuItemAction>][];
}

export interface IMenuService {
    // ... existing stuff

  getMenuData(id: MenuId): IMenuData;
}

IMO this would encapsulate things nicer and clearly separate live IMenu-instances from just menu data which you to handle yourselves.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love it. I'll make the change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this further, I'm not sure we should separate the contexts from the menu. At the time menu is created it has a specific set of contexts. If you create that menu again later with a different scoped context key service you could have different contexts and different actions. I would propose that we have the IMenuData, and then have 2 additions to IMenuService:

/**
 * The "dead" counterpart to `createMenu`.
 * For other components to use.
 **/
getMenuActions(id: MenudId, contextKeyService: IContextKeyService, options?: IMenuActionOptions): [string, Array<MenuItemAction | SubmenuItemAction>][];

/**
 * This is what the tree view will use to create a "dead" menu and get the contexts
 **/
getMenuData(id: MenudId, contextKeyService: IContextKeyService, options?: IMenuActionOptions): IMenuData;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the time menu is created it has a specific set of contexts. If you create that menu again later with a different scoped context key service you could have different contexts and different actions.

Not contexts but context evaluations. The former are statically defined when you register menus items (mostly via Action2) and those (keys) should be enough to know what to listen on. The menu does exactly that which in convenient but wasteful when you have very many menu instances for the same menu-id.

So, likely we need getMenuActions with the signature you have outlined above and then getMenuData is without the CKS-argument but just returning the context keys (for listening).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I think I'm missing something still then since I think we still need the CKS for getMenuData. The items that get added to the menu depend on the CKS that is passed in. In the tree, we even make an overlay:

const contextKeyService = this.contextKeyService.createOverlay([
['view', this.id],
['viewItem', element.contextValue]
]);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. IMenuService#getMenuAction(menuId, CKS, options?) -> update DOM
  2. IMenuService#getMenuContext(menuId) -> Set -> CKS -> listen and check with set
getMenuContextKeys(id: MenudId): Set<string>

@alexr00 alexr00 requested a review from jrieken July 5, 2024 11:58
Copy link
Member Author

@alexr00 alexr00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrieken, this is ready for review again. I will adop the new getMenuActions method in places where it's obvious in a follow up PR.

@alexr00 alexr00 merged commit 603b0ee into main Jul 8, 2024
6 checks passed
@alexr00 alexr00 deleted the alexr00/naval-antelope branch July 8, 2024 08:05
aaronchucarroll pushed a commit to aaronchucarroll/vscode that referenced this pull request Jul 10, 2024
* Don't listen on menu changed, method 2
This time, instead of only updating the tree elements who's actions are visible (selected, focused, focusing), update all tree items that the context change applies to, as before. However, the context key change event is now per tree renderer, not per menu.
Fixes microsoft#213145

* Implement feedback

* 💄
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[08e] potential listener LEAK detected, having 183 listeners already. MOST frequent listener (33):
4 participants