mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-06 01:25:38 -05:00
Show notification if there are projects that haven't been added to the workspace (#14046)
* add check for if there are projects that haven't been added to the workspace * add check when workspace folders change * add comment * update wording * filter for multiple file extensions at the same time * add test * addressing comments
This commit is contained in:
@@ -17,6 +17,13 @@ export const WorkspaceRequiredMessage = localize('dataworkspace.workspaceRequire
|
||||
export const OpenWorkspace = localize('dataworkspace.openWorkspace', "Open Workspace…");
|
||||
export const CreateWorkspaceConfirmation = localize('dataworkspace.createWorkspaceConfirmation', "A new workspace will be created and opened in order to open project. The Extension Host will restart and if there is a folder currently open, it will be closed.");
|
||||
export const EnterWorkspaceConfirmation = localize('dataworkspace.enterWorkspaceConfirmation', "To open this workspace, the Extension Host will restart and if there is a workspace or folder currently open, it will be closed.");
|
||||
export const WorkspaceContainsNotAddedProjects = localize('dataworkspace.workspaceContainsNotAddedProjects', "The current workspace contains one or more projects that have not been added to the workspace. Use the 'Open existing' dialog to add projects to the projects pane.");
|
||||
export const LaunchOpenExisitingDialog = localize('dataworkspace.launchOpenExistingDialog', "Launch Open existing dialog");
|
||||
export const DoNotShowAgain = localize('dataworkspace.doNotShowAgain', "Do not show again");
|
||||
|
||||
// config settings
|
||||
export const projectsConfigurationKey = 'projects';
|
||||
export const showNotAddedProjectsMessageKey = 'showNotAddedProjectsInWorkspacePrompt';
|
||||
|
||||
// UI
|
||||
export const OkButtonText = localize('dataworkspace.ok', "OK");
|
||||
|
||||
@@ -16,6 +16,11 @@ import { IconPathHelper } from './common/iconHelper';
|
||||
export function activate(context: vscode.ExtensionContext): Promise<IExtension> {
|
||||
const workspaceService = new WorkspaceService(context);
|
||||
workspaceService.loadTempProjects();
|
||||
workspaceService.checkForProjectsNotAddedToWorkspace();
|
||||
context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(() => {
|
||||
workspaceService.checkForProjectsNotAddedToWorkspace();
|
||||
}));
|
||||
|
||||
const workspaceTreeDataProvider = new WorkspaceTreeDataProvider(workspaceService);
|
||||
const dataWorkspaceExtension = new DataWorkspaceExtension(workspaceService);
|
||||
context.subscriptions.push(vscode.window.registerTreeDataProvider('dataworkspace.views.main', workspaceTreeDataProvider));
|
||||
|
||||
@@ -8,6 +8,7 @@ import * as vscode from 'vscode';
|
||||
import * as dataworkspace from 'dataworkspace';
|
||||
import * as path from 'path';
|
||||
import * as constants from '../common/constants';
|
||||
import * as glob from 'fast-glob';
|
||||
import { IWorkspaceService } from '../common/interfaces';
|
||||
import { ProjectProviderRegistry } from '../common/projectProviderRegistry';
|
||||
import Logger from '../common/logger';
|
||||
@@ -158,6 +159,65 @@ export class WorkspaceService implements IWorkspaceService {
|
||||
return vscode.workspace.workspaceFile ? this.getWorkspaceConfigurationValue<string[]>(ProjectsConfigurationName).map(project => this.toUri(project)) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for projects that are in the workspace folders but have not been added to the workspace through the dialog or by editing the .code-workspace file
|
||||
*/
|
||||
async checkForProjectsNotAddedToWorkspace(): Promise<void> {
|
||||
const config = vscode.workspace.getConfiguration(constants.projectsConfigurationKey);
|
||||
|
||||
// only check if the user hasn't selected not to show this prompt again
|
||||
if (!config[constants.showNotAddedProjectsMessageKey]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// look for any projects that haven't been added to the workspace
|
||||
const projectsInWorkspace = this.getProjectsInWorkspace();
|
||||
const workspaceFolders = vscode.workspace.workspaceFolders;
|
||||
|
||||
if (!workspaceFolders) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const folder of workspaceFolders) {
|
||||
const results = await this.getAllProjectsInWorkspaceFolder(folder);
|
||||
|
||||
let containsNotAddedProject = false;
|
||||
for (const projFile of results) {
|
||||
// if any of the found projects aren't already in the workspace's projects, we can stop checking and show the info message
|
||||
if (!projectsInWorkspace.find(p => p.fsPath === projFile)) {
|
||||
containsNotAddedProject = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (containsNotAddedProject) {
|
||||
const result = await vscode.window.showInformationMessage(constants.WorkspaceContainsNotAddedProjects, constants.LaunchOpenExisitingDialog, constants.DoNotShowAgain);
|
||||
if (result === constants.LaunchOpenExisitingDialog) {
|
||||
// open settings
|
||||
await vscode.commands.executeCommand('projects.openExisting');
|
||||
} else if (result === constants.DoNotShowAgain) {
|
||||
await config.update(constants.showNotAddedProjectsMessageKey, false, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getAllProjectsInWorkspaceFolder(folder: vscode.WorkspaceFolder): Promise<string[]> {
|
||||
// get the unique supported project extensions
|
||||
const supportedProjectExtensions = [...new Set((await this.getAllProjectTypes()).map(p => { return p.projectFileExtension; }))];
|
||||
|
||||
// path needs to use forward slashes for glob to work
|
||||
const escapedPath = glob.escapePath(folder.uri.fsPath.replace(/\\/g, '/'));
|
||||
|
||||
// can filter for multiple file extensions using folder/**/*.{sqlproj,csproj} format, but this notation doesn't work if there's only one extension
|
||||
// so the filter needs to be in the format folder/**/*.sqlproj if there's only one supported projectextension
|
||||
const projFilter = supportedProjectExtensions.length > 1 ? path.posix.join(escapedPath, '**', `*.{${supportedProjectExtensions.toString()}}`) : path.posix.join(escapedPath, '**', `*.${supportedProjectExtensions[0]}`);
|
||||
|
||||
return await glob(projFilter);
|
||||
}
|
||||
|
||||
async getProjectProvider(projectFile: vscode.Uri): Promise<dataworkspace.IProjectProvider | undefined> {
|
||||
const projectType = path.extname(projectFile.path).replace(/\./g, '');
|
||||
let provider = ProjectProviderRegistry.getProviderByProjectExtension(projectType);
|
||||
|
||||
@@ -10,10 +10,10 @@ import * as sinon from 'sinon';
|
||||
import * as should from 'should';
|
||||
import * as path from 'path';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import * as constants from '../common/constants';
|
||||
import { WorkspaceService } from '../services/workspaceService';
|
||||
import { ProjectProviderRegistry } from '../common/projectProviderRegistry';
|
||||
import { createProjectProvider } from './projectProviderRegistry.test';
|
||||
import { ProjectAlreadyOpened } from '../common/constants';
|
||||
|
||||
const DefaultWorkspaceFilePath = '/test/folder/ws.code-workspace';
|
||||
|
||||
@@ -223,7 +223,7 @@ suite('WorkspaceService Tests', function (): void {
|
||||
should.strictEqual(updateConfigurationStub.calledOnce, true, 'update configuration should have been called once');
|
||||
should.strictEqual(updateWorkspaceFoldersStub.calledOnce, true, 'updateWorkspaceFolders should have been called once');
|
||||
should.strictEqual(showInformationMessageStub.calledOnce, true, 'showInformationMessage should be called once');
|
||||
should(showInformationMessageStub.calledWith(ProjectAlreadyOpened(processPath('/test/folder/folder1/proj2.sqlproj')))).be.true(`showInformationMessage not called with expected message '${ProjectAlreadyOpened(processPath('/test/folder/folder1/proj2.sqlproj'))}' Actual '${showInformationMessageStub.getCall(0).args[0]}'`);
|
||||
should(showInformationMessageStub.calledWith(constants.ProjectAlreadyOpened(processPath('/test/folder/folder1/proj2.sqlproj')))).be.true(`showInformationMessage not called with expected message '${constants.ProjectAlreadyOpened(processPath('/test/folder/folder1/proj2.sqlproj'))}' Actual '${showInformationMessageStub.getCall(0).args[0]}'`);
|
||||
should.strictEqual(updateConfigurationStub.calledWith('projects', sinon.match.array.deepEquals([
|
||||
processPath('folder1/proj2.sqlproj'),
|
||||
processPath('proj1.sqlproj'),
|
||||
@@ -295,4 +295,30 @@ suite('WorkspaceService Tests', function (): void {
|
||||
onWorkspaceProjectsChangedDisposable.dispose();
|
||||
});
|
||||
|
||||
test('test checkForProjectsNotAddedToWorkspace', async () => {
|
||||
const previousSetting = await vscode.workspace.getConfiguration(constants.projectsConfigurationKey)[constants.showNotAddedProjectsMessageKey];
|
||||
await vscode.workspace.getConfiguration(constants.projectsConfigurationKey).update(constants.showNotAddedProjectsMessageKey, true, true);
|
||||
|
||||
sinon.stub(service, 'getProjectsInWorkspace').returns([vscode.Uri.file('abc.sqlproj'), vscode.Uri.file('folder1/abc1.sqlproj')]);
|
||||
sinon.stub(vscode.workspace, 'workspaceFolders').value([{uri: vscode.Uri.file('.')}]);
|
||||
sinon.stub(service, 'getAllProjectTypes').resolves([{
|
||||
projectFileExtension: 'sqlproj',
|
||||
id: 'sql project',
|
||||
displayName: 'sql project',
|
||||
description: '',
|
||||
icon: ''
|
||||
}]);
|
||||
const infoMessageStub = sinon.stub(vscode.window, 'showInformationMessage').resolves(<any>constants.DoNotShowAgain);
|
||||
const getProjectsInwWorkspaceFolderStub = sinon.stub(service, 'getAllProjectsInWorkspaceFolder').resolves([vscode.Uri.file('abc.sqlproj').fsPath, vscode.Uri.file('folder1/abc1.sqlproj').fsPath]);
|
||||
|
||||
await service.checkForProjectsNotAddedToWorkspace();
|
||||
should(infoMessageStub.notCalled).be.true('Should not have found projects not added to workspace');
|
||||
|
||||
// add a project to the workspace folder not added to the workspace yet
|
||||
getProjectsInwWorkspaceFolderStub.resolves([vscode.Uri.file('abc.sqlproj').fsPath, vscode.Uri.file('folder1/abc1.sqlproj').fsPath, vscode.Uri.file('folder2/abc2.sqlproj').fsPath]);
|
||||
await service.checkForProjectsNotAddedToWorkspace();
|
||||
should(infoMessageStub.calledOnce).be.true('Should have found a project that was not added to the workspace');
|
||||
|
||||
await vscode.workspace.getConfiguration(constants.projectsConfigurationKey).update(constants.showNotAddedProjectsMessageKey, previousSetting, true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user