Files
azuredatastudio/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts
Benjin Dubishar 0ac6a07c5f Fix for Sqlproj tree bug (#10605)
Fixes bug where files located in a subfolder defined before the folders themselves in .sqlproj would result in those files not appearing in the ADS treeview
2020-06-01 22:41:00 -07:00

98 lines
3.3 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as path from 'path';
import { DataSourcesTreeItem } from './dataSourceTreeItem';
import { BaseProjectTreeItem } from './baseTreeItem';
import * as fileTree from './fileFolderTreeItem';
import { Project, ProjectEntry, EntryType } from '../project';
import * as utils from '../../common/utils';
/**
* TreeNode root that represents an entire project
*/
export class ProjectRootTreeItem extends BaseProjectTreeItem {
dataSourceNode: DataSourcesTreeItem;
fileChildren: { [childName: string]: (fileTree.FolderNode | fileTree.FileNode) } = {};
project: Project;
constructor(project: Project) {
super(vscode.Uri.parse(path.basename(project.projectFilePath)), undefined);
this.project = project;
this.dataSourceNode = new DataSourcesTreeItem(this);
this.construct();
}
public get children(): BaseProjectTreeItem[] {
const output: BaseProjectTreeItem[] = [];
output.push(this.dataSourceNode);
return output.concat(Object.values(this.fileChildren).sort(fileTree.sortFileFolderNodes));
}
public get treeItem(): vscode.TreeItem {
return new vscode.TreeItem(this.uri, vscode.TreeItemCollapsibleState.Expanded);
}
/**
* Processes the list of files in a project file to constructs the tree
*/
private construct() {
for (const entry of this.project.files) {
const parentNode = this.getEntryParentNode(entry);
if (Object.keys(parentNode.fileChildren).includes(path.basename(entry.fsUri.path))) {
continue; // ignore duplicate entries
}
let newNode: fileTree.FolderNode | fileTree.FileNode;
switch (entry.type) {
case EntryType.File:
newNode = new fileTree.FileNode(entry.fsUri, parentNode);
break;
case EntryType.Folder:
newNode = new fileTree.FolderNode(entry.fsUri, parentNode);
break;
default:
throw new Error(`Unknown EntryType: '${entry.type}'`);
}
parentNode.fileChildren[path.basename(entry.fsUri.path)] = newNode;
}
}
/**
* Gets the immediate parent tree node for an entry in a project file
*/
private getEntryParentNode(entry: ProjectEntry): fileTree.FolderNode | ProjectRootTreeItem {
const relativePathParts = utils.trimChars(utils.trimUri(vscode.Uri.file(this.project.projectFilePath), entry.fsUri), '/').split('/').slice(0, -1); // remove the last part because we only care about the parent
if (relativePathParts.length === 0) {
return this; // if nothing left after trimming the entry itself, must been root
}
let current: fileTree.FolderNode | ProjectRootTreeItem = this;
for (const part of relativePathParts) {
if (current.fileChildren[part] === undefined) {
current.fileChildren[part] = new fileTree.FolderNode(vscode.Uri.file(path.join(path.dirname(this.project.projectFilePath), part)), current);
}
if (current.fileChildren[part] instanceof fileTree.FileNode) {
return current;
}
else {
current = current.fileChildren[part] as fileTree.FolderNode | ProjectRootTreeItem;
}
}
return current;
}
}