Have different node types for the different item types in sql project tree (#22053)

* Have different node types for the different item types in sql project tree

* address comments
This commit is contained in:
Kim Santiago
2023-02-28 10:31:46 -08:00
committed by GitHub
parent 555f8fbb1e
commit 8550faaa73
4 changed files with 105 additions and 31 deletions

View File

@@ -564,7 +564,12 @@ export enum DatabaseProjectItemType {
reference = 'databaseProject.itemType.reference',
dataSourceRoot = 'databaseProject.itemType.dataSourceRoot',
sqlcmdVariablesRoot = 'databaseProject.itemType.sqlcmdVariablesRoot',
sqlcmdVariable = 'databaseProject.itemType.sqlcmdVariable'
sqlcmdVariable = 'databaseProject.itemType.sqlcmdVariable',
preDeploy = 'databaseProject.itemType.file.preDeploymentScript',
postDeploy = 'databaseProject.itemType.file.postDeployScript',
none = 'databaseProject.itemType.file.noneFile',
sqlObjectFile = 'databaseProject.itemType.file.sqlObjectScript',
publishProfile = 'databaseProject.itemType.file.publishProfile'
}
// AutoRest

View File

@@ -38,7 +38,7 @@ export class FolderNode extends BaseProjectTreeItem {
/**
* Node representing a file in a project
*/
export class FileNode extends BaseProjectTreeItem {
export abstract class FileNode extends BaseProjectTreeItem {
public fileSystemUri: vscode.Uri;
constructor(filePath: vscode.Uri, sqlprojUri: vscode.Uri) {
@@ -65,7 +65,16 @@ export class FileNode extends BaseProjectTreeItem {
}
}
export class ExternalStreamingJobFileNode extends FileNode {
export class SqlObjectFileNode extends FileNode {
public override get treeItem(): vscode.TreeItem {
const treeItem = super.treeItem;
treeItem.contextValue = DatabaseProjectItemType.sqlObjectFile;
return treeItem;
}
}
export class ExternalStreamingJobFileNode extends SqlObjectFileNode {
public override get treeItem(): vscode.TreeItem {
const treeItem = super.treeItem;
treeItem.contextValue = DatabaseProjectItemType.externalStreamingJob;
@@ -74,7 +83,7 @@ export class ExternalStreamingJobFileNode extends FileNode {
}
}
export class TableFileNode extends FileNode {
export class TableFileNode extends SqlObjectFileNode {
public override get treeItem(): vscode.TreeItem {
const treeItem = super.treeItem;
treeItem.contextValue = DatabaseProjectItemType.table;
@@ -83,6 +92,42 @@ export class TableFileNode extends FileNode {
}
}
export class PreDeployNode extends FileNode {
public override get treeItem(): vscode.TreeItem {
const treeItem = super.treeItem;
treeItem.contextValue = DatabaseProjectItemType.preDeploy;
return treeItem;
}
}
export class PostDeployNode extends FileNode {
public override get treeItem(): vscode.TreeItem {
const treeItem = super.treeItem;
treeItem.contextValue = DatabaseProjectItemType.postDeploy;
return treeItem;
}
}
export class NoneNode extends FileNode {
public override get treeItem(): vscode.TreeItem {
const treeItem = super.treeItem;
treeItem.contextValue = DatabaseProjectItemType.none;
return treeItem;
}
}
export class PublishProfileNode extends FileNode {
public override get treeItem(): vscode.TreeItem {
const treeItem = super.treeItem;
treeItem.contextValue = DatabaseProjectItemType.publishProfile;
return treeItem;
}
}
/**
* Compares two folder/file tree nodes so that folders come before files, then alphabetically
* @param a a folder or file tree node

View File

@@ -62,23 +62,32 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
* Processes the list of files in a project file to constructs the tree
*/
private construct() {
let treeItemList = this.project.files
.concat(this.project.preDeployScripts)
.concat(this.project.postDeployScripts)
.concat(this.project.noneDeployScripts)
.concat(this.project.publishProfiles);
// pre deploy scripts
for (const preDeployEntry of this.project.preDeployScripts) {
const newNode = new fileTree.PreDeployNode(preDeployEntry.fsUri, this.projectFileUri);
this.addNode(newNode, preDeployEntry);
}
for (const entry of treeItemList) {
if (entry.type !== EntryType.File && entry.relativePath.startsWith(RelativeOuterPath)) {
continue;
}
// post deploy scripts
for (const postDeployEntry of this.project.postDeployScripts) {
const newNode = new fileTree.PostDeployNode(postDeployEntry.fsUri, this.projectFileUri);
this.addNode(newNode, postDeployEntry);
}
const parentNode = this.getEntryParentNode(entry);
// none scripts
for (const noneEntry of this.project.noneDeployScripts) {
const newNode = new fileTree.NoneNode(noneEntry.fsUri, this.projectFileUri);
this.addNode(newNode, noneEntry);
}
if (Object.keys(parentNode.fileChildren).includes(path.basename(entry.fsUri.path))) {
continue; // ignore duplicate entries
}
// publish profiles
for (const publishProfile of this.project.publishProfiles) {
const newNode = new fileTree.PublishProfileNode(publishProfile.fsUri, this.projectFileUri);
this.addNode(newNode, publishProfile);
}
// sql object scripts and folders
for (const entry of this.project.files) {
let newNode: fileTree.FolderNode | fileTree.FileNode;
switch (entry.type) {
@@ -89,7 +98,7 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
newNode = new fileTree.TableFileNode(entry.fsUri, this.projectFileUri);
}
else {
newNode = new fileTree.FileNode(entry.fsUri, this.projectFileUri);
newNode = new fileTree.SqlObjectFileNode(entry.fsUri, this.projectFileUri);
}
break;
@@ -100,10 +109,25 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
throw new Error(`Unknown EntryType: '${entry.type}'`);
}
parentNode.fileChildren[path.basename(entry.fsUri.path)] = newNode;
this.addNode(newNode, entry);
}
}
private addNode(newNode: fileTree.FileNode | fileTree.FolderNode, entry: FileProjectEntry): void {
// Don't add external folders
if (entry.type !== EntryType.File && entry.relativePath.startsWith(RelativeOuterPath)) {
return;
}
const parentNode = this.getEntryParentNode(entry);
if (Object.keys(parentNode.fileChildren).includes(path.basename(entry.fsUri.path))) {
return; // ignore duplicate entries
}
parentNode.fileChildren[path.basename(entry.fsUri.path)] = newNode;
}
/**
* Gets the immediate parent tree node for an entry in a project file
*/

View File

@@ -9,7 +9,7 @@ import * as os from 'os';
import * as path from 'path';
import { Project } from '../models/project';
import { FolderNode, FileNode, sortFileFolderNodes } from '../models/tree/fileFolderTreeItem';
import { FolderNode, FileNode, sortFileFolderNodes, SqlObjectFileNode } from '../models/tree/fileFolderTreeItem';
import { ProjectRootTreeItem } from '../models/tree/projectTreeItem';
import { DatabaseProjectItemType } from '../common/constants';
import { EntryType } from 'sqldbproj';
@@ -21,12 +21,12 @@ describe('Project Tree tests', function (): void {
const sqlprojUri = vscode.Uri.file(`${root}Fake.sqlproj`);
let inputNodes: (FileNode | FolderNode)[] = [
new FileNode(vscode.Uri.file(`${root}C`), sqlprojUri),
new FileNode(vscode.Uri.file(`${root}D`), sqlprojUri),
new SqlObjectFileNode(vscode.Uri.file(`${root}C`), sqlprojUri),
new SqlObjectFileNode(vscode.Uri.file(`${root}D`), sqlprojUri),
new FolderNode(vscode.Uri.file(`${root}Z`), sqlprojUri),
new FolderNode(vscode.Uri.file(`${root}X`), sqlprojUri),
new FileNode(vscode.Uri.file(`${root}B`), sqlprojUri),
new FileNode(vscode.Uri.file(`${root}A`), sqlprojUri),
new SqlObjectFileNode(vscode.Uri.file(`${root}B`), sqlprojUri),
new SqlObjectFileNode(vscode.Uri.file(`${root}A`), sqlprojUri),
new FolderNode(vscode.Uri.file(`${root}W`), sqlprojUri),
new FolderNode(vscode.Uri.file(`${root}Y`), sqlprojUri)
];
@@ -38,10 +38,10 @@ describe('Project Tree tests', function (): void {
new FolderNode(vscode.Uri.file(`${root}X`), sqlprojUri),
new FolderNode(vscode.Uri.file(`${root}Y`), sqlprojUri),
new FolderNode(vscode.Uri.file(`${root}Z`), sqlprojUri),
new FileNode(vscode.Uri.file(`${root}A`), sqlprojUri),
new FileNode(vscode.Uri.file(`${root}B`), sqlprojUri),
new FileNode(vscode.Uri.file(`${root}C`), sqlprojUri),
new FileNode(vscode.Uri.file(`${root}D`), sqlprojUri)
new SqlObjectFileNode(vscode.Uri.file(`${root}A`), sqlprojUri),
new SqlObjectFileNode(vscode.Uri.file(`${root}B`), sqlprojUri),
new SqlObjectFileNode(vscode.Uri.file(`${root}C`), sqlprojUri),
new SqlObjectFileNode(vscode.Uri.file(`${root}D`), sqlprojUri)
];
should(inputNodes.map(n => n.relativeProjectUri.path)).deepEqual(expectedNodes.map(n => n.relativeProjectUri.path));
@@ -86,13 +86,13 @@ describe('Project Tree tests', function (): void {
DatabaseProjectItemType.sqlcmdVariablesRoot,
DatabaseProjectItemType.folder,
DatabaseProjectItemType.folder,
DatabaseProjectItemType.file]);
DatabaseProjectItemType.sqlObjectFile]);
should(tree.children.find(x => x.relativeProjectUri.path === '/TestProj/someFolder')?.children.map(y => y.treeItem.contextValue)).deepEqual([
DatabaseProjectItemType.folder,
DatabaseProjectItemType.folder,
DatabaseProjectItemType.file,
DatabaseProjectItemType.file]);
DatabaseProjectItemType.sqlObjectFile,
DatabaseProjectItemType.sqlObjectFile]);
});
it('Should be able to parse windows relative path as platform safe path', function (): void {