Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit c0ccf6c

Browse files
paracyclevinistock
andauthored
Add ability to show current file in Dependencies tree view (#1019)
* Add ability to show current file in Dependencies tree view By watching the `onDidChangeActiveTextEditor` event, we can reveal the current file in the Dependencies tree view. To be able to do that, however, we need to implement `getParent` method on `DependenciesTree` class. This method is used by VS Code to find the parent of a given node. In our case, we want to return the parent of a given file node, which is either a `GemDirectoryNode` or a `Dependency` node, depending on whether the parent directory is the root path of a gem or not. Moreover, when we can `TreeView.reveal` method to reveal a node, VSCode forces the tree view to be visible, which is a little jarring if the user has hidden the tree view. To avoid that, we store the current item to reveal in an instance variable, and reveal it when the tree view becomes visible again. If the tree view is already visible, we reveal the item immediately. * Use path to determine if we're at root * Respect auto reveal option when showing files from gems --------- Co-authored-by: Vinicius Stock <vinicius.stock@shopify.com>
1 parent a70af33 commit c0ccf6c

1 file changed

Lines changed: 101 additions & 13 deletions

File tree

src/dependenciesTree.ts

Lines changed: 101 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import path from "path";
2+
13
import * as vscode from "vscode";
24

35
import { STATUS_EMITTER, WorkspaceInterface } from "./common";
@@ -20,26 +22,29 @@ export class DependenciesTree
2022

2123
private currentWorkspace: WorkspaceInterface | undefined;
2224
private readonly treeView: vscode.TreeView<BundlerTreeNode>;
23-
private readonly workspaceListener: vscode.Disposable;
25+
private readonly subscriptions: vscode.Disposable[] = [];
26+
private gemRootFolders: Record<string, Dependency | undefined> = {};
27+
private currentVisibleItem: GemFilePath | undefined;
2428

2529
constructor() {
2630
this.treeView = vscode.window.createTreeView("dependencies", {
2731
treeDataProvider: this,
2832
showCollapseAll: true,
2933
});
3034

31-
this.workspaceListener = STATUS_EMITTER.event((workspace) => {
32-
if (!workspace || workspace === this.currentWorkspace) {
33-
return;
34-
}
35-
36-
this.currentWorkspace = workspace;
37-
this.refresh();
38-
});
35+
this.subscriptions.push(
36+
STATUS_EMITTER.event(this.workspaceDidChange.bind(this)),
37+
vscode.window.onDidChangeActiveTextEditor(
38+
this.activeEditorDidChange.bind(this),
39+
),
40+
this.treeView.onDidChangeVisibility(
41+
this.treeVisibilityDidChange.bind(this),
42+
),
43+
);
3944
}
4045

4146
dispose(): void {
42-
this.workspaceListener.dispose();
47+
this.subscriptions.forEach((item) => item.dispose());
4348
this.treeView.dispose();
4449
}
4550

@@ -59,12 +64,86 @@ export class DependenciesTree
5964
}
6065
}
6166

62-
refresh(): void {
67+
getParent(element: BundlerTreeNode): vscode.ProviderResult<BundlerTreeNode> {
68+
const parentUri = vscode.Uri.joinPath(element.resourceUri, "..");
69+
const rootPath = path.parse(parentUri.path).root;
70+
71+
if (parentUri.path === rootPath) {
72+
return undefined;
73+
}
74+
75+
if (element instanceof GemDirectoryPath || element instanceof GemFilePath) {
76+
// Look up the parent in the cache of gem root folders. This allows us
77+
// to stop the directory tree traversal at some gem root folder.
78+
const dependency = this.gemRootFolders[parentUri.toString()];
79+
80+
if (dependency) {
81+
return dependency;
82+
} else {
83+
return new GemDirectoryPath(parentUri);
84+
}
85+
} else {
86+
return undefined;
87+
}
88+
}
89+
90+
private refresh(): void {
6391
this.fetchDependencies();
6492
this._onDidChangeTreeData.fire(undefined);
6593
}
6694

95+
private workspaceDidChange(workspace: WorkspaceInterface | undefined): void {
96+
if (!workspace || workspace === this.currentWorkspace) {
97+
return;
98+
}
99+
100+
this.currentWorkspace = workspace;
101+
this.refresh();
102+
}
103+
104+
private activeEditorDidChange(editor: vscode.TextEditor | undefined): void {
105+
const uri = editor?.document.uri;
106+
107+
if (!uri) {
108+
return;
109+
}
110+
111+
// In case the tree view is not visible, we need to remember the current
112+
// visible item, so that we can reveal it when the tree view becomes visible.
113+
this.currentVisibleItem = new GemFilePath(uri);
114+
115+
if (this.treeView.visible) {
116+
this.revealElement(this.currentVisibleItem);
117+
}
118+
}
119+
120+
private treeVisibilityDidChange(
121+
event: vscode.TreeViewVisibilityChangeEvent,
122+
): void {
123+
if (this.currentVisibleItem && event.visible) {
124+
this.revealElement(this.currentVisibleItem);
125+
}
126+
}
127+
128+
private revealElement(element: BundlerTreeNode): void {
129+
const autoReveal: boolean | undefined = vscode.workspace
130+
.getConfiguration("explorer")
131+
.get("autoReveal");
132+
133+
if (autoReveal) {
134+
this.treeView.reveal(element, {
135+
select: true,
136+
focus: false,
137+
expand: true,
138+
});
139+
}
140+
141+
this.currentVisibleItem = undefined;
142+
}
143+
67144
private async fetchDependencies(): Promise<BundlerTreeNode[]> {
145+
this.gemRootFolders = {};
146+
68147
if (!this.currentWorkspace) {
69148
return [];
70149
}
@@ -76,7 +155,7 @@ export class DependenciesTree
76155
{ name: string; version: string; path: string; dependency: boolean },
77156
];
78157

79-
return resp
158+
const dependencies = resp
80159
.sort((left, right) => {
81160
if (left.dependency === right.dependency) {
82161
// if the two dependencies are the same, sort by name
@@ -87,8 +166,17 @@ export class DependenciesTree
87166
}
88167
})
89168
.map((dep) => {
90-
return new Dependency(dep.name, dep.version, vscode.Uri.file(dep.path));
169+
const uri = vscode.Uri.file(dep.path);
170+
const dependency = new Dependency(dep.name, dep.version, uri);
171+
this.gemRootFolders[uri.toString()] = dependency;
172+
return dependency;
91173
});
174+
175+
dependencies.forEach((dep) => {
176+
this.gemRootFolders[dep.resourceUri.toString()] = dep;
177+
});
178+
179+
return dependencies;
92180
}
93181
}
94182

0 commit comments

Comments
 (0)