Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'editors/code/src/dependencies_provider.ts')
| -rw-r--r-- | editors/code/src/dependencies_provider.ts | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/editors/code/src/dependencies_provider.ts b/editors/code/src/dependencies_provider.ts new file mode 100644 index 0000000000..8900aa9a5f --- /dev/null +++ b/editors/code/src/dependencies_provider.ts @@ -0,0 +1,148 @@ +import * as vscode from "vscode"; +import * as fspath from "path"; +import * as fs from "fs"; +import { CtxInit } from "./ctx"; +import * as ra from "./lsp_ext"; +import { FetchDependencyListResult } from "./lsp_ext"; + +export class RustDependenciesProvider + implements vscode.TreeDataProvider<Dependency | DependencyFile> +{ + dependenciesMap: { [id: string]: Dependency | DependencyFile }; + ctx: CtxInit; + + constructor(ctx: CtxInit) { + this.dependenciesMap = {}; + this.ctx = ctx; + } + + private _onDidChangeTreeData: vscode.EventEmitter< + Dependency | DependencyFile | undefined | null | void + > = new vscode.EventEmitter<Dependency | undefined | null | void>(); + + readonly onDidChangeTreeData: vscode.Event< + Dependency | DependencyFile | undefined | null | void + > = this._onDidChangeTreeData.event; + + getDependency(filePath: string): Dependency | DependencyFile | undefined { + return this.dependenciesMap[filePath.toLowerCase()]; + } + + contains(filePath: string): boolean { + return filePath.toLowerCase() in this.dependenciesMap; + } + + isInitialized(): boolean { + return Object.keys(this.dependenciesMap).length !== 0; + } + + refresh(): void { + this.dependenciesMap = {}; + this._onDidChangeTreeData.fire(); + } + + getParent?( + element: Dependency | DependencyFile + ): vscode.ProviderResult<Dependency | DependencyFile> { + if (element instanceof Dependency) return undefined; + return element.parent; + } + + getTreeItem(element: Dependency | DependencyFile): vscode.TreeItem | Thenable<vscode.TreeItem> { + if (element.id! in this.dependenciesMap) return this.dependenciesMap[element.id!]; + return element; + } + + getChildren( + element?: Dependency | DependencyFile + ): vscode.ProviderResult<Dependency[] | DependencyFile[]> { + return new Promise((resolve, _reject) => { + if (!vscode.workspace.workspaceFolders) { + void vscode.window.showInformationMessage("No dependency in empty workspace"); + return Promise.resolve([]); + } + if (element) { + const files = fs.readdirSync(element.dependencyPath).map((fileName) => { + const filePath = fspath.join(element.dependencyPath, fileName); + const collapsibleState = fs.lstatSync(filePath).isDirectory() + ? vscode.TreeItemCollapsibleState.Collapsed + : vscode.TreeItemCollapsibleState.None; + const dep = new DependencyFile(fileName, filePath, element, collapsibleState); + this.dependenciesMap[dep.dependencyPath.toLowerCase()] = dep; + return dep; + }); + return resolve(files); + } else { + return resolve(this.getRootDependencies()); + } + }); + } + + private async getRootDependencies(): Promise<Dependency[]> { + const dependenciesResult: FetchDependencyListResult = await this.ctx.client.sendRequest( + ra.fetchDependencyList, + {} + ); + const crates = dependenciesResult.crates; + + return crates + .map((crate) => { + const dep = this.toDep(crate.name || "unknown", crate.version || "", crate.path); + this.dependenciesMap[dep.dependencyPath.toLowerCase()] = dep; + return dep; + }) + .sort((a, b) => { + return a.label.localeCompare(b.label); + }); + } + + private toDep(moduleName: string, version: string, path: string): Dependency { + return new Dependency( + moduleName, + version, + vscode.Uri.parse(path).fsPath, + vscode.TreeItemCollapsibleState.Collapsed + ); + } +} + +export class Dependency extends vscode.TreeItem { + constructor( + public readonly label: string, + private version: string, + readonly dependencyPath: string, + public readonly collapsibleState: vscode.TreeItemCollapsibleState + ) { + super(label, collapsibleState); + this.resourceUri = vscode.Uri.file(dependencyPath); + this.id = this.resourceUri.fsPath.toLowerCase(); + this.description = this.version; + if (this.version) { + this.tooltip = `${this.label}-${this.version}`; + } else { + this.tooltip = this.label; + } + } +} + +export class DependencyFile extends vscode.TreeItem { + constructor( + readonly label: string, + readonly dependencyPath: string, + readonly parent: Dependency | DependencyFile, + public readonly collapsibleState: vscode.TreeItemCollapsibleState + ) { + super(vscode.Uri.file(dependencyPath), collapsibleState); + this.id = this.resourceUri!.fsPath.toLowerCase(); + const isDir = fs.lstatSync(this.resourceUri!.fsPath).isDirectory(); + if (!isDir) { + this.command = { + command: "vscode.open", + title: "Open File", + arguments: [this.resourceUri], + }; + } + } +} + +export type DependencyId = { id: string }; |