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

Guard against identical ID's in plugin tree view #12338

Conversation

colin-grant-work
Copy link
Contributor

What it does

Fixes #12337 mostly by bringing in VSCode's approach to the same problem.

How to test

  1. Follow procedure in New PluginTree ID generation algorithm generates identical ID's #12337
  2. All references should be rendered separately, and application should not crash.

Review checklist

Reminder for reviewers

@colin-grant-work colin-grant-work added tree issues related to the tree (ex: tree widget) plug-in system issues related to the plug-in system labels Mar 22, 2023
@tsmaeder
Copy link
Contributor

tsmaeder commented Mar 23, 2023

@colin-grant-work I'm a bit confuse, because the API documentation of TreeItem clearly states:

Optional id for the tree item that has to be unique across tree. The id is used to preserve the selection and expansion state of the tree item.

Is the "references view" built in extension not compliant with the published API?

@tsmaeder
Copy link
Contributor

Ah, I see: the trouble is that we calculate a "pseudo-id" based on the label which can be the same for multiple items.

id = TreeViewExtImpl.ID_COMPUTED + this.nextItemId++;
// Modeled on https://github.com/microsoft/vscode/blob/main/src/vs/workbench/api/common/extHostTreeViews.ts#L822
private buildTreeItemId(parentId: string, item: TreeItem, mustReturnNew: boolean): string {
if (item.id) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We still need the logic to construct paths from ID's for all the reasons in https://github.com/eclipse-theia/theia/pull/12120/files. While the incremental tree update is running, a node might be in more than one place at the same time. The drag/drop example helps from the PR helps test this.

Copy link
Contributor Author

@colin-grant-work colin-grant-work Mar 23, 2023

Choose a reason for hiding this comment

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

This logic does use the parent ID as part of the ID if it's present:

const prefix: string = parentId ? parentId : TreeViewExtImpl.ID_COMPUTED;

Copy link
Contributor

Choose a reason for hiding this comment

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

It also needs to be done for items that have an id set. Otherwise reparenting items does not work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code does seem to work with the example extension from your drag and drop PR. Do you have a concrete example where this would fail?

Copy link
Contributor

Choose a reason for hiding this comment

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

I was able to reproduce the problem from #12111 eventually. The simple scenario from the bug does not reproduce the problem reliably, but randomly dragging elements around for a while eventually triggered the stack overflow. The problem seems to be timing-dependent.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've pushed a change that includes the parent's ID for plugin-supplied ID's as well as computed ID's.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm thinking this might be a problem because we're using the same separator for the path separator and the prefix separator. Let's think about an element that has the id /i/parent/child. The tree item id will be i/i/parent/child. Wouldn't that be the same id we get when we compute the id of an element with id child, whose parent is an element with id parent? Because the computed id of the parent is i/parent, so the expression becomes ${'i'}/${'i/parent'}/'child' = i/i/parent/child.

Come to think of it, we might have to escape the path separator in given id's in order to prevent this "attack". Sorry to make seemingly trivial change so complicated 🤦

@tsmaeder
Copy link
Contributor

The current version fixes the problem with D&D reparenting.

Copy link
Contributor

@tsmaeder tsmaeder left a comment

Choose a reason for hiding this comment

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

Fine to merge from my side: I still think we could construct an example where unescaped weird id values could wreak havoc, but that situation is no worse than before, so not an obstacle to merging the PR.

@colin-grant-work colin-grant-work force-pushed the bugfix/plugin-tree-ids branch from 531182f to e0779a7 Compare April 4, 2023 20:00
@colin-grant-work colin-grant-work merged commit af15a37 into eclipse-theia:master Apr 4, 2023
@colin-grant-work colin-grant-work deleted the bugfix/plugin-tree-ids branch April 4, 2023 20:52
@colin-grant-work colin-grant-work added this to the 1.37.0 milestone Apr 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plug-in system issues related to the plug-in system tree issues related to the tree (ex: tree widget)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New PluginTree ID generation algorithm generates identical ID's
2 participants