.sqlproj and datasources.json file parsing (#8921)

* Checkpoint

* Adding mock contents for tree

* added open sqlproj dialog

* reading files from directory

* Added directory traversal

* Adding tree sorting by folder vs file and label

* Improved auto-unfolding of tree based on node type

* replacing fs with fs.promise alias

* PR feedback

* added activation event for when workspace contains sqlproj files

* Returning after displaying error

* Fixing linter errors

* Reworked tree

* Fixing missing grandchildren

* Correcting tree URI construction

* Refactoring to isolate tree item responsibilities from data model responsibilities

* project file parsing

* constructing tree from project files rather than filesystem

* Fixing double-initialization

* Changing projectEntry to take enum for file type

* Correct node type for project item

* Parsing datasources.json

* Child nodes for sql data source

* Localizing strings

* Checkpoint

* Adding mock contents for tree

* added open sqlproj dialog

* reading files from directory

* Added directory traversal

* Adding tree sorting by folder vs file and label

* Improved auto-unfolding of tree based on node type

* replacing fs with fs.promise alias

* PR feedback

* added activation event for when workspace contains sqlproj files

* Returning after displaying error

* Fixing linter errors

* Reworked tree

* Fixing missing grandchildren

* Correcting tree URI construction

* Refactoring to isolate tree item responsibilities from data model responsibilities

* project file parsing

* constructing tree from project files rather than filesystem

* Fixing double-initialization

* Changing projectEntry to take enum for file type

* Correct node type for project item

* Parsing datasources.json

* Child nodes for sql data source

* Localizing strings

* missed file in merge

* changed extension method to helper

* cleanup

* Adding docstrings
This commit is contained in:
Benjin Dubishar
2020-02-24 12:11:41 -08:00
committed by GitHub
parent 933cfb21ef
commit 1a639f83c4
18 changed files with 718 additions and 152 deletions

View File

@@ -4,38 +4,34 @@
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { promises as fs } from 'fs';
import * as path from 'path';
import * as constants from '../common/constants';
import { SqlDatabaseProjectItem } from './databaseProjectTreeItem';
import { BaseProjectTreeItem, MessageTreeItem } from '../models/tree/baseTreeItem';
import { ProjectRootTreeItem } from '../models/tree/projectTreeItem';
import { Project } from '../models/project';
export class SqlDatabaseProjectTreeViewProvider implements vscode.TreeDataProvider<SqlDatabaseProjectItem> {
private _onDidChangeTreeData: vscode.EventEmitter<SqlDatabaseProjectItem | undefined> = new vscode.EventEmitter<SqlDatabaseProjectItem | undefined>();
readonly onDidChangeTreeData: vscode.Event<SqlDatabaseProjectItem | undefined> = this._onDidChangeTreeData.event;
/**
* Tree view for database projects
*/
export class SqlDatabaseProjectTreeViewProvider implements vscode.TreeDataProvider<BaseProjectTreeItem> {
private _onDidChangeTreeData: vscode.EventEmitter<BaseProjectTreeItem | undefined> = new vscode.EventEmitter<BaseProjectTreeItem | undefined>();
readonly onDidChangeTreeData: vscode.Event<BaseProjectTreeItem | undefined> = this._onDidChangeTreeData.event;
private roots: SqlDatabaseProjectItem[] = [];
private roots: BaseProjectTreeItem[] = [];
constructor() {
this.initialize();
}
private initialize() {
this.roots = [new SqlDatabaseProjectItem(constants.noOpenProjectMessage, false)];
this.roots = [new MessageTreeItem(constants.noOpenProjectMessage)];
}
public getTreeItem(element: SqlDatabaseProjectItem): vscode.TreeItem {
return {
label: element.label,
collapsibleState: element.parent === undefined
? vscode.TreeItemCollapsibleState.Expanded
: element.isFolder
? vscode.TreeItemCollapsibleState.Collapsed
: vscode.TreeItemCollapsibleState.None
};
public getTreeItem(element: BaseProjectTreeItem): vscode.TreeItem {
return element.treeItem;
}
public getChildren(element?: SqlDatabaseProjectItem): SqlDatabaseProjectItem[] {
public getChildren(element?: BaseProjectTreeItem): BaseProjectTreeItem[] {
if (element === undefined) {
return this.roots;
}
@@ -43,78 +39,19 @@ export class SqlDatabaseProjectTreeViewProvider implements vscode.TreeDataProvid
return element.children;
}
public async openProject(projectFiles: vscode.Uri[]) {
if (projectFiles.length > 1) { // TODO: how to handle opening a folder with multiple .sqlproj files?
vscode.window.showErrorMessage(constants.multipleSqlProjFiles);
return;
}
if (projectFiles.length === 0) {
public load(projects: Project[]) {
if (projects.length === 0) {
vscode.window.showErrorMessage(constants.noSqlProjFiles);
return;
}
let directoryPath = path.dirname(projectFiles[0].fsPath);
console.log('Opening project directory: ' + directoryPath);
let newRoots: BaseProjectTreeItem[] = [];
let newRoots: SqlDatabaseProjectItem[] = [];
newRoots.push(await this.constructDataSourcesTree(directoryPath));
newRoots.push(await this.constructProjectTree(directoryPath));
for (const proj of projects) {
newRoots.push(new ProjectRootTreeItem(proj));
}
this.roots = newRoots;
this._onDidChangeTreeData.fire();
}
private async constructProjectTree(directoryPath: string): Promise<SqlDatabaseProjectItem> {
let projectsNode = await this.constructFileTreeNode(directoryPath, undefined);
projectsNode.label = constants.projectNodeName;
return projectsNode;
}
private async constructFileTreeNode(entryPath: string, parentNode: SqlDatabaseProjectItem | undefined): Promise<SqlDatabaseProjectItem> {
let stat = await fs.stat(entryPath);
let output = parentNode === undefined
? new SqlDatabaseProjectItem(path.basename(entryPath), stat.isDirectory())
: parentNode.createChild(path.basename(entryPath), stat.isDirectory());
if (stat.isDirectory()) {
let contents = await fs.readdir(entryPath);
for (const entry of contents) {
await this.constructFileTreeNode(path.join(entryPath, entry), output);
}
// sort children so that folders come first, then alphabetical
output.children.sort((a: SqlDatabaseProjectItem, b: SqlDatabaseProjectItem) => {
if (a.isFolder && !b.isFolder) { return -1; }
else if (!a.isFolder && b.isFolder) { return 1; }
else { return a.label.localeCompare(b.label); }
});
}
return output;
}
private async constructDataSourcesTree(directoryPath: string): Promise<SqlDatabaseProjectItem> {
let dataSourceNode = new SqlDatabaseProjectItem(constants.dataSourcesNodeName, true);
let dataSourcesFilePath = path.join(directoryPath, constants.dataSourcesFileName);
try {
let connections = await fs.readFile(dataSourcesFilePath, 'r');
// TODO: parse connections.json
dataSourceNode.createChild(constants.foundDataSourcesFile + connections.length, false);
}
catch {
dataSourceNode.createChild(constants.noDataSourcesFile, false);
}
return dataSourceNode;
}
}