All files / views/trees/workspace-tree workspace-node-provider.ts

94.59% Statements 35/37
100% Branches 20/20
80% Functions 8/10
94.28% Lines 33/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108                            18x   18x     25x         18x           1x       3x   3x                 6x 2x     4x 3x     4x   4x   1x   1x 3x   1x   1x     2x 2x   2x 1x         4x       8x 8x   8x 8x         9x 8x 8x   8x 2x             8x            
import * as vscode from 'vscode';
import { Utils } from 'vscode-uri';
import { container } from 'tsyringe';
import { ServiceToken } from '@src/services/tokens';
import { IWorkspaceFileService } from '@src/services/core';
 
// For a complete implementation of the FileSystemProvider API, see:
// https://github.com/boltex/revealRangeTest/blob/main/src/fileExplorer.ts#L185
 
/**
 * A tree node provider for RDF files in the Visual Studio Code workspace.
 */
export class WorkspaceNodeProvider implements vscode.TreeDataProvider<string> {
 
	private _onDidChangeTreeData = new vscode.EventEmitter<string | undefined>();
 
	readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
 
	private get workspaceFileService() {
		return container.resolve<IWorkspaceFileService>(ServiceToken.WorkspaceFileService);
	}
 
	constructor() {
		// Monitor for changes in the workspace folders.
		this.workspaceFileService.onDidChangeFiles((e) => {
			this._onDidChangeTreeData.fire(e.uri.toString());
		});
	}
 
	refresh(): void {
		this._onDidChangeTreeData.fire(undefined);
	}
 
	getParent(uri: string): string | undefined {
		let resourceUri = vscode.Uri.parse(uri);
 
		return uri ? Utils.dirname(resourceUri).toString() : undefined;
	}
 
	/**
	 * Get the children of a folder.
	 * @param uri The URI of the folder to get children for or `undefined` for the root.
	 * @returns An array of child URIs, sorted by folders first and then by name.
	 */
	async getChildren(uri?: string): Promise<string[]> {
		if (!vscode.workspace.name || !vscode.workspace.workspaceFolders?.length) {
			return [];
		}
 
		if (!uri) {
			await this.workspaceFileService.waitForDiscovery();
		}
 
		const result = [];
 
		if (uri) {
			// If the URI is provided, get the contents of the specified folder.
			const folder = vscode.Uri.parse(uri);
 
			result.push(...(await this.workspaceFileService.getFolderContents(folder)));
		} else if (!vscode.workspace.workspaceFile) {
			// If this is not a workspace, then return the contents of the first folder.
			const folder = vscode.workspace.workspaceFolders[0].uri;
 
			result.push(...(await this.workspaceFileService.getFolderContents(folder)));
		} else {
			// Iterate the workspace folders and push only the ones that have contents.
			for (const folder of vscode.workspace.workspaceFolders) {
				const contents = await this.workspaceFileService.getFolderContents(folder.uri);
 
				if (contents.length > 0) {
					result.push(folder.uri);
				}
			}
		}
 
		return result.map((resource) => resource.toString());
	}
 
	getTreeItem(uri: string): vscode.TreeItem {
		const resourceUri = vscode.Uri.parse(uri);
		const isDirectory = Utils.extname(resourceUri) == '';
 
		const item = new vscode.TreeItem(uri);
		item.resourceUri = resourceUri;
 
		// Use the workspace folder name when the URI matches a top-level workspace folder.
		// This respects custom folder names defined in a .code-workspace file,
		// keeping the tree consistent with the VS Code Explorer.
		const workspaceFolder = vscode.workspace.workspaceFolders?.find(f => f.uri.toString() === uri);
		item.label = workspaceFolder?.name ?? decodeURIComponent(Utils.basename(resourceUri));
		item.collapsibleState = isDirectory ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None;
 
		if (!isDirectory) {
			item.command = {
				command: 'vscode.open',
				arguments: [uri],
				title: 'Open File'
			};
		}
 
		return item;
	}
 
	getTotalItemCount(): number {
		return 0;
	}
}