mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
@@ -46,6 +46,10 @@
|
|||||||
"title": "%refresh-workspace-command%",
|
"title": "%refresh-workspace-command%",
|
||||||
"category": "",
|
"category": "",
|
||||||
"icon": "$(refresh)"
|
"icon": "$(refresh)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "projects.removeProject",
|
||||||
|
"title": "%remove-project-command%"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"menus": {
|
"menus": {
|
||||||
@@ -69,6 +73,17 @@
|
|||||||
{
|
{
|
||||||
"command": "dataworkspace.refresh",
|
"command": "dataworkspace.refresh",
|
||||||
"when": "false"
|
"when": "false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "projects.removeProject",
|
||||||
|
"when": "false"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"view/item/context": [
|
||||||
|
{
|
||||||
|
"command": "projects.removeProject",
|
||||||
|
"when": "view == dataworkspace.views.main && viewItem == databaseProject.itemType.project",
|
||||||
|
"group": "9_dbProjectsLast@9"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,5 +4,6 @@
|
|||||||
"data-workspace-view-container-name": "Projects",
|
"data-workspace-view-container-name": "Projects",
|
||||||
"main-view-name": "Projects",
|
"main-view-name": "Projects",
|
||||||
"add-project-command": "Add Project",
|
"add-project-command": "Add Project",
|
||||||
"refresh-workspace-command": "Refresh"
|
"refresh-workspace-command": "Refresh",
|
||||||
|
"remove-project-command":"Remove Project"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,17 @@ export interface IWorkspaceService {
|
|||||||
* @param projectFiles the list of project files to be added, the project file should be absolute path.
|
* @param projectFiles the list of project files to be added, the project file should be absolute path.
|
||||||
*/
|
*/
|
||||||
addProjectsToWorkspace(projectFiles: vscode.Uri[]): Promise<void>;
|
addProjectsToWorkspace(projectFiles: vscode.Uri[]): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the project from workspace
|
||||||
|
* @param projectFile The project file to be removed
|
||||||
|
*/
|
||||||
|
removeProject(projectFile: vscode.Uri): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event fires when projects in workspace changes
|
||||||
|
*/
|
||||||
|
readonly onDidWorkspaceProjectsChange: vscode.Event<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,7 +11,11 @@ import { UnknownProjectsErrorMessage } from './constants';
|
|||||||
* Tree data provider for the workspace main view
|
* Tree data provider for the workspace main view
|
||||||
*/
|
*/
|
||||||
export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider<WorkspaceTreeItem>{
|
export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider<WorkspaceTreeItem>{
|
||||||
constructor(private _workspaceService: IWorkspaceService) { }
|
constructor(private _workspaceService: IWorkspaceService) {
|
||||||
|
this._workspaceService.onDidWorkspaceProjectsChange(() => {
|
||||||
|
this.refresh();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private _onDidChangeTreeData: vscode.EventEmitter<void | WorkspaceTreeItem | null | undefined> | undefined = new vscode.EventEmitter<WorkspaceTreeItem | undefined | void>();
|
private _onDidChangeTreeData: vscode.EventEmitter<void | WorkspaceTreeItem | null | undefined> | undefined = new vscode.EventEmitter<WorkspaceTreeItem | undefined | void>();
|
||||||
readonly onDidChangeTreeData?: vscode.Event<void | WorkspaceTreeItem | null | undefined> | undefined = this._onDidChangeTreeData?.event;
|
readonly onDidChangeTreeData?: vscode.Event<void | WorkspaceTreeItem | null | undefined> | undefined = this._onDidChangeTreeData?.event;
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ declare module 'dataworkspace' {
|
|||||||
*/
|
*/
|
||||||
getProjectTreeDataProvider(projectFile: vscode.Uri): Promise<vscode.TreeDataProvider<any>>;
|
getProjectTreeDataProvider(projectFile: vscode.Uri): Promise<vscode.TreeDataProvider<any>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the project provider extension that the specified project file has been removed from the data workspace
|
||||||
|
* @param projectFile The Uri of the project file
|
||||||
|
*/
|
||||||
|
RemoveProject(projectFile: vscode.Uri): Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the supported project types
|
* Gets the supported project types
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { WorkspaceTreeDataProvider } from './common/workspaceTreeDataProvider';
|
|||||||
import { WorkspaceService } from './services/workspaceService';
|
import { WorkspaceService } from './services/workspaceService';
|
||||||
import { DataWorkspaceExtension } from './dataWorkspaceExtension';
|
import { DataWorkspaceExtension } from './dataWorkspaceExtension';
|
||||||
import { SelectProjectFileActionName } from './common/constants';
|
import { SelectProjectFileActionName } from './common/constants';
|
||||||
|
import { WorkspaceTreeItem } from './common/interfaces';
|
||||||
|
|
||||||
export async function activate(context: vscode.ExtensionContext): Promise<dataworkspace.IExtension> {
|
export async function activate(context: vscode.ExtensionContext): Promise<dataworkspace.IExtension> {
|
||||||
const workspaceService = new WorkspaceService();
|
const workspaceService = new WorkspaceService();
|
||||||
@@ -36,7 +37,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<datawo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await workspaceService.addProjectsToWorkspace(fileUris);
|
await workspaceService.addProjectsToWorkspace(fileUris);
|
||||||
workspaceTreeDataProvider.refresh();
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -44,6 +44,10 @@ export async function activate(context: vscode.ExtensionContext): Promise<datawo
|
|||||||
workspaceTreeDataProvider.refresh();
|
workspaceTreeDataProvider.refresh();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
context.subscriptions.push(vscode.commands.registerCommand('projects.removeProject', async (treeItem: WorkspaceTreeItem) => {
|
||||||
|
await workspaceService.removeProject(vscode.Uri.file(treeItem.element.project.projectFilePath));
|
||||||
|
}));
|
||||||
|
|
||||||
return new DataWorkspaceExtension();
|
return new DataWorkspaceExtension();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ const WorkspaceConfigurationName = 'dataworkspace';
|
|||||||
const ProjectsConfigurationName = 'projects';
|
const ProjectsConfigurationName = 'projects';
|
||||||
|
|
||||||
export class WorkspaceService implements IWorkspaceService {
|
export class WorkspaceService implements IWorkspaceService {
|
||||||
|
private _onDidWorkspaceProjectsChange: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();
|
||||||
|
readonly onDidWorkspaceProjectsChange: vscode.Event<void> = this._onDidWorkspaceProjectsChange?.event;
|
||||||
|
|
||||||
async addProjectsToWorkspace(projectFiles: vscode.Uri[]): Promise<void> {
|
async addProjectsToWorkspace(projectFiles: vscode.Uri[]): Promise<void> {
|
||||||
if (vscode.workspace.workspaceFile) {
|
if (vscode.workspace.workspaceFile) {
|
||||||
const currentProjects: vscode.Uri[] = await this.getProjectsInWorkspace();
|
const currentProjects: vscode.Uri[] = await this.getProjectsInWorkspace();
|
||||||
@@ -37,6 +40,7 @@ export class WorkspaceService implements IWorkspaceService {
|
|||||||
if (newProjectFileAdded) {
|
if (newProjectFileAdded) {
|
||||||
// Save the new set of projects to the workspace configuration.
|
// Save the new set of projects to the workspace configuration.
|
||||||
await this.setWorkspaceConfigurationValue(ProjectsConfigurationName, currentProjects.map(project => this.toRelativePath(project)));
|
await this.setWorkspaceConfigurationValue(ProjectsConfigurationName, currentProjects.map(project => this.toRelativePath(project)));
|
||||||
|
this._onDidWorkspaceProjectsChange.fire();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newWorkspaceFolders.length > 0) {
|
if (newWorkspaceFolders.length > 0) {
|
||||||
@@ -68,6 +72,18 @@ export class WorkspaceService implements IWorkspaceService {
|
|||||||
return ProjectProviderRegistry.getProviderByProjectType(projectType);
|
return ProjectProviderRegistry.getProviderByProjectType(projectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async removeProject(projectFile: vscode.Uri): Promise<void> {
|
||||||
|
if (vscode.workspace.workspaceFile) {
|
||||||
|
const currentProjects: vscode.Uri[] = await this.getProjectsInWorkspace();
|
||||||
|
const projectIdx = currentProjects.findIndex((p: vscode.Uri) => p.fsPath === projectFile.fsPath);
|
||||||
|
if (projectIdx !== -1) {
|
||||||
|
currentProjects.splice(projectIdx, 1);
|
||||||
|
await this.setWorkspaceConfigurationValue(ProjectsConfigurationName, currentProjects.map(project => this.toRelativePath(project)));
|
||||||
|
this._onDidWorkspaceProjectsChange.fire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure the project provider extension for the specified project is loaded
|
* Ensure the project provider extension for the specified project is loaded
|
||||||
* @param projectType The file extension of the project, if not specified, all project provider extensions will be loaded.
|
* @param projectType The file extension of the project, if not specified, all project provider extensions will be loaded.
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ export function createProjectProvider(projectTypes: IProjectType[]): IProjectPro
|
|||||||
const treeDataProvider = new MockTreeDataProvider();
|
const treeDataProvider = new MockTreeDataProvider();
|
||||||
const projectProvider: IProjectProvider = {
|
const projectProvider: IProjectProvider = {
|
||||||
supportedProjectTypes: projectTypes,
|
supportedProjectTypes: projectTypes,
|
||||||
|
RemoveProject: (projectFile: vscode.Uri): Promise<void> => {
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
getProjectTreeDataProvider: (projectFile: vscode.Uri): Promise<vscode.TreeDataProvider<any>> => {
|
getProjectTreeDataProvider: (projectFile: vscode.Uri): Promise<vscode.TreeDataProvider<any>> => {
|
||||||
return Promise.resolve(treeDataProvider);
|
return Promise.resolve(treeDataProvider);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,6 +186,10 @@ suite('WorkspaceService Tests', function (): void {
|
|||||||
stubWorkspaceFile(DefaultWorkspaceFilePath);
|
stubWorkspaceFile(DefaultWorkspaceFilePath);
|
||||||
const updateConfigurationStub = sinon.stub();
|
const updateConfigurationStub = sinon.stub();
|
||||||
const getConfigurationStub = sinon.stub().returns([processPath('folder1/proj2.sqlproj')]);
|
const getConfigurationStub = sinon.stub().returns([processPath('folder1/proj2.sqlproj')]);
|
||||||
|
const onWorkspaceProjectsChangedStub = sinon.stub();
|
||||||
|
const onWorkspaceProjectsChangedDisposable = service.onDidWorkspaceProjectsChange(() => {
|
||||||
|
onWorkspaceProjectsChangedStub();
|
||||||
|
});
|
||||||
stubGetConfigurationValue(getConfigurationStub, updateConfigurationStub);
|
stubGetConfigurationValue(getConfigurationStub, updateConfigurationStub);
|
||||||
const asRelativeStub = sinon.stub(vscode.workspace, 'asRelativePath');
|
const asRelativeStub = sinon.stub(vscode.workspace, 'asRelativePath');
|
||||||
sinon.stub(vscode.workspace, 'workspaceFolders').value(['.']);
|
sinon.stub(vscode.workspace, 'workspaceFolders').value(['.']);
|
||||||
@@ -207,5 +211,28 @@ suite('WorkspaceService Tests', function (): void {
|
|||||||
should.strictEqual(updateWorkspaceFoldersStub.calledWith(1, null, sinon.match((arg) => {
|
should.strictEqual(updateWorkspaceFoldersStub.calledWith(1, null, sinon.match((arg) => {
|
||||||
return arg.uri.path === '/test/other';
|
return arg.uri.path === '/test/other';
|
||||||
})), true, 'updateWorkspaceFolder parameters does not match expectation');
|
})), true, 'updateWorkspaceFolder parameters does not match expectation');
|
||||||
|
should.strictEqual(onWorkspaceProjectsChangedStub.calledOnce, true, 'the onDidWorkspaceProjectsChange event should have been fired');
|
||||||
|
onWorkspaceProjectsChangedDisposable.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('test removeProject', async () => {
|
||||||
|
const processPath = (original: string): string => {
|
||||||
|
return original.replace(/\//g, path.sep);
|
||||||
|
};
|
||||||
|
stubWorkspaceFile(DefaultWorkspaceFilePath);
|
||||||
|
const updateConfigurationStub = sinon.stub();
|
||||||
|
const getConfigurationStub = sinon.stub().returns([processPath('folder1/proj2.sqlproj'), processPath('folder2/proj3.sqlproj')]);
|
||||||
|
const onWorkspaceProjectsChangedStub = sinon.stub();
|
||||||
|
const onWorkspaceProjectsChangedDisposable = service.onDidWorkspaceProjectsChange(() => {
|
||||||
|
onWorkspaceProjectsChangedStub();
|
||||||
|
});
|
||||||
|
stubGetConfigurationValue(getConfigurationStub, updateConfigurationStub);
|
||||||
|
await service.removeProject(vscode.Uri.file('/test/folder/folder1/proj2.sqlproj'));
|
||||||
|
should.strictEqual(updateConfigurationStub.calledWith('projects', sinon.match.array.deepEquals([
|
||||||
|
processPath('folder2/proj3.sqlproj')
|
||||||
|
]), vscode.ConfigurationTarget.Workspace), true, 'updateConfiguration parameters does not match expectation for remove project');
|
||||||
|
should.strictEqual(onWorkspaceProjectsChangedStub.calledOnce, true, 'the onDidWorkspaceProjectsChange event should have been fired');
|
||||||
|
onWorkspaceProjectsChangedDisposable.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ suite('workspaceTreeDataProvider Tests', function (): void {
|
|||||||
icon: '',
|
icon: '',
|
||||||
displayName: 'sql project'
|
displayName: 'sql project'
|
||||||
}],
|
}],
|
||||||
|
RemoveProject: (projectFile: vscode.Uri): Promise<void> => {
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
getProjectTreeDataProvider: (projectFile: vscode.Uri): Promise<vscode.TreeDataProvider<any>> => {
|
getProjectTreeDataProvider: (projectFile: vscode.Uri): Promise<vscode.TreeDataProvider<any>> => {
|
||||||
return Promise.resolve(treeDataProvider);
|
return Promise.resolve(treeDataProvider);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,7 +342,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "sqlDatabaseProjects.close",
|
"command": "sqlDatabaseProjects.close",
|
||||||
"when": "view =~ /^(sqlDatabaseProjectsView|dataworkspace.views.main)$/ && viewItem == databaseProject.itemType.project",
|
"when": "view == sqlDatabaseProjectsView && viewItem == databaseProject.itemType.project",
|
||||||
"group": "9_dbProjectsLast@9"
|
"group": "9_dbProjectsLast@9"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -24,6 +24,16 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
|
|||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback method when a project has been removed from the workspace view
|
||||||
|
* @param projectFile The Uri of the project file
|
||||||
|
*/
|
||||||
|
RemoveProject(projectFile: vscode.Uri): Promise<void> {
|
||||||
|
// No resource release needed
|
||||||
|
console.log(`project file unloaded: ${projectFile.fsPath}`);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the supported project types
|
* Gets the supported project types
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user