Skip to content

Commit

Permalink
Follow VSCode's strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
colin-grant-work committed Mar 22, 2023
1 parent dacd392 commit 61f78ce
Showing 1 changed file with 28 additions and 15 deletions.
43 changes: 28 additions & 15 deletions packages/plugin-ext/src/plugin/tree/tree-views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
// TODO: extract `@theia/util` for event, disposable, cancellation and common types
// don't use @theia/core directly from plugin host
import { Emitter } from '@theia/core/lib/common/event';
import { basename } from '@theia/core/lib/common/paths';
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
import { DataTransfer, DataTransferItem, Disposable as PluginDisposable, ThemeIcon } from '../types-impl';
import { Plugin, PLUGIN_RPC_CONTEXT, TreeViewsExt, TreeViewsMain, TreeViewItem, TreeViewRevealOptions, DataTransferFileDTO } from '../../common/plugin-api-rpc';
Expand Down Expand Up @@ -188,8 +189,6 @@ class TreeViewExtImpl<T> implements Disposable {
private static readonly ID_COMPUTED = 'c';
private static readonly ID_ITEM = 'i';

private nextItemId: 0;

private readonly onDidExpandElementEmitter = new Emitter<TreeViewExpansionEvent<T>>();
readonly onDidExpandElement = this.onDidExpandElementEmitter.event;

Expand Down Expand Up @@ -315,7 +314,7 @@ class TreeViewExtImpl<T> implements Disposable {
// parent is inconsistent
return undefined;
}
const candidateId = this.buildTreeItemId(parentId, treeItem);
const candidateId = this.buildTreeItemId(parentId, treeItem, false);
if (this.nodes.has(candidateId)) {
return chain.concat(candidateId);
}
Expand Down Expand Up @@ -346,18 +345,32 @@ class TreeViewExtImpl<T> implements Disposable {
return idLabel;
}

private buildTreeItemId(parentId: string, item: TreeItem): string {
// build tree id according to https://code.visualstudio.com/api/references/vscode-api#TreeItem
// note: the front end tree implementation cannot handle reparenting items, hence the id is set to the "path" of individual ids
let id = typeof item.id === 'string' ? item.id : this.getItemLabel(item);
if (id) {
// we use '' as the id of the root, we don't consider that a valid id
// since '' is falsy, we'll never get '' in this branch
id = TreeViewExtImpl.ID_ITEM + id;
} else {
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) {
return `${TreeViewExtImpl.ID_ITEM}/${item.id}`;
}
return `${parentId}/${id}`;

const treeItemLabel = this.getItemLabel(item);
const prefix: string = parentId ? parentId : TreeViewExtImpl.ID_COMPUTED;
let elementId = treeItemLabel ? treeItemLabel : item.resourceUri ? basename(item.resourceUri.fsPath) : '';
elementId = elementId.indexOf('/') !== -1 ? elementId.replace('/', '//') : elementId;
const childrenNodes = (this.nodes.get(parentId)?.children || []);

let id: string;
let counter = 0;
do {
id = `${prefix}/${counter}:${elementId}`;
if (!mustReturnNew || !this.nodes.has(id) || this.nodes.get(id) === item) {
// Return first if asked for or
// Return if handle does not exist or
// Return if handle is being reused
break;
}
counter++;
} while (counter <= childrenNodes.length);

return id;
}

async getChildren(parentId: string): Promise<TreeViewItem[] | undefined> {
Expand Down Expand Up @@ -389,7 +402,7 @@ class TreeViewExtImpl<T> implements Disposable {

// Generate the ID
// ID is used for caching the element
const id = this.buildTreeItemId(parentId, treeItem);
const id = this.buildTreeItemId(parentId, treeItem, true);

const toDisposeElement = new DisposableCollection();
const node: TreeExtNode<T> = {
Expand Down

0 comments on commit 61f78ce

Please sign in to comment.